I am looking for a way to specify the possible status codes that a route can respond with, besides the default 200 "OK" and 500 "internal server error", with a different content type header, as errors are handled by a handler function hooked into the plumbed API and return "application/json" as opposed to "text/html", similar to the implementation at the bottom of this article: https://unconj.ca/blog/structured-errors-in-plumber-apis.html
I have an API built using the "annotation" style, an example route here:
# Define the Plumber API using annotations
#* @get /predict/<file_id>
#* @param file_id:string ID or name of the RDS file
#* @serializer html
function(res, req, file_id) {
future::future({
loaded_model <- list()
loaded_model <- find_or_download_model(file_id, env_var$model_local_dir,
env_var$model_s3_bucket, env_var$model_s3_endpoint, env_var$s3_accesskey,
env_var$s3_secretkey)
return("Success, File Found.")
})
}
Which works fine. However, when I try to add @response annotations to the route, such as:
# Define the Plumber API using annotations
#* @get /predict/<file_id>
#* @param file_id:string ID or name of the RDS file
#* @serializer html
#* @response 403 Forbidden <== HERE
#* @response 404 Not Found <== AND HERE
I end up with the following generated API, which doesn't have the desired Content Type of "application/json" for the 403 and 404 responses: 
(Which is annoying, because the default 500 Error Code Handler has the correct content type!)
Can anyone offer any suggestions for possible fixes please?
From some digging, it looks like only the Description field of a response object is parsed from the plumber comment block. However, you can specify more details if you add the path programmatically (or even add onto your definition).
You can still define your main code in
plumber.R(or whatever). Here's what I have inplumber.Rfor this example:The error stuff here is just so I can see things in action, and raises an important point: The stuff we'll define for the responses is PURELY for the OpenAPI description/swagger doc; it doesn't actually impact the returned response.
Now let's tell the API spec about our responses:
Rather surprisingly (to me), the function in the file "wins" over the function in the call to
pr_get().You can clean that up a bit using a function for the error message:
Or, even better, a function that signals a typed error (similar to the thing shown in the blog, but really use that status code), combined with an error handler:
I'll be digging through and finding more details for the book I'm working on, Web APIs with R (which is why I found this question, while searching for detailed examples of responses in plumber definitions).