Appendix C — Plumber vs. Plumber2 Syntax
Why plumber2 exists
plumber and plumber2 both turn R functions into web APIs, and both define routes with #* annotation comments. plumber2 changes what the handler receives (a parsed body and query instead of req), renames the response object, and adds api(), api_get(), and api_post() for building routers in code.
Comparing Syntax
Defining routes
Plumber
In plumber, annotations define the HTTP method, path, and parameters, and each parameter arrives as a function argument:
#* @get /hello
#* @param name The name to greet
function(name = "World") {
list(message = paste("Hello", name))
}Plumber2
plumber2 keeps the annotations. Query parameters are declared with @query (with a type) and arrive together in the query argument:
#* @get /hello
#* @query name:string The name to greet
function(query) {
list(message = paste("Hello", query$name))
}Handling request bodies
Plumber
In plumber, the handler reads the request through req and sets status codes on res:
#* @post /predict
function(req, res) {
data <- req$body
if (!is.data.frame(data)) {
res$status <- 400
return(list(error = "Input must be a data frame"))
}
# ... prediction logic
}Plumber2
plumber2 parses the JSON body before the handler runs and passes it in as body; response replaces res:
#* @post /predict
#* @serializer json
function(body, response) {
if (!is.data.frame(body)) {
response$status <- 400L
return(list(error = "Input must be a data frame"))
}
# ... prediction logic
}Which should you choose?
| Feature | plumber |
plumber2 |
|---|---|---|
| Route definition | #* annotations or pr_get()/pr_post() |
#* annotations or api_get()/api_post() |
| Router object | pr() |
api() |
| Request data | Arguments and req$body |
Parsed query and body arguments |
| Response object | res |
response |
| Parameter types | Documented with @param |
Declared with @query name:type |
Recap
Pick
plumberwhen you’re following the original do4ds text or maintaining an API already written with it. Handlers read the request throughreqand set status codes onres, and routers are built withpr(),pr_get(), andpr_post(); theplumberchapter builds the penguin API this way.Pick
plumber2when you’re starting a new API and want the request handled for you. It parses the JSON body before the handler runs, declares typed query parameters with@query name:type, and builds routers withapi(),api_get(), andapi_post(); theplumber2chapter rebuilds the same API with this syntax.