I am currently using the Luminus template with the +swagger option, which adds compojure-api support.
My current setup is like so (only relevant bits):
(ns my-project.routes.services
(:require [compojure.api.sweet :refer :all]
,,,)
(defapi service-routes
(POST "/login" req
:return Result
:body [user UserLogin]
:summary "Log the user in"
(auth/login! req user))
(defapi restricted-service-routes
(POST "/login2" req
:return Result
:body [user UserLogin]
:summary "Log the user in"
(auth/login! req user)))
and
(ns my-project.handler)
(:require [my-project.routes.services :refer :all])
(defroutes app-routes
#'service-routes
#'restricted-service-routes)
When the server receives the request, it is passed to app-routes
.
I then used the Swagger UI to test these routes, and the "/login"
route worked
fine. However, the completely similar "/login2"
returns
{
"errors": "(not (map? nil))"
}
When I switch the order of the two service groups, the result is as expected: the first route works fine, while the second will not receive the body
.
Is this a bug with Compojure-api itself? And is there anything I can do to work around this?
defapi
macro seems to wrap all the routes to api-middleware
(check out compojure-api source code) which includes wrap-params
middleware.
In your setup, you are chaining two set of routes both wrapped in the api-middleware
and thus calling the wrap-params
middleware on a request in case of the second defapi
route (/login2) twice. The first call of wrap-params
resolves the params correctly but the second wrap-params
call has nothing to process and thus your code ends up with runtime error.
To solve your issue, try to disable default wrapping by api-middleware
for all your defapi
usages but one. See the :disable-api-middleware
option in the link above.