compojure-api allows you to define the return schema:
(s/defschema Pizza
{:name s/Str})
(GET "/pizza/:id" [id]
:return Pizza
:summary "returns a Pizza"
(ok (get-pizza id)))
My issue is when the get-pizza fn returns a 404 {:status 404 :body {:message "Invalid id provided"}} the response (to the requester) is that that 404 does not match the Pizza schema:
{
"errors": {
"name": "missing-required-key",
"status": "disallowed-key",
"body": "disallowed-key"
}
}
The docs show that you can provide multiple response schemas but I am unclear on what my get-pizza fn should return in order to utilize those schemas. Their example uses the ring-http-response lib to generate the return values, but there is no difference between my return value for get-pizza and the ring-http-response 'not found' fn.
Truthfully I would rather not use the :responses param if possible because I can already foresee all the code duplication. Before specifying the :return Schema I was able to have my get-pizza fn return a 404 and be correctly passed onto the requester but once I added the Schema I was no longer able to do that. I considered having the return value be :return (s/one Pizza Error) where Error would be a generically defined error map but I don't see why I would do this for every route if all calls could in theory return a 500.
Note: The reason I switched to utilizing the :return param is that it makes the generated swagger-ui docs much prettier & easier to understand.
You have a small issue in your code I assume as you didn't show implementation of your
get-pizza [id]function.You return
{:status 404 :body {:message "Invalid ID provided}}which is then wrapped into HTTP 200 response by(ok (get-pizza id)).Your
get-pizzafunction should return a pizza or nil if not found. Your HTTP response should be generated based on that in your route:The original example from compojure-api repo has a bit different implementation where for
nilvalues fromget-pizzait will still return HTTP 200 response with empty response body. According to your question you would return 404 instead and the code above should meet your requirement.