Reputation: 12983
I have an application using Compojure with this sort of endpoint
(defroutes routes
(POST "/api/v1/echo" req (str req))
(def http-handler
(reload/wrap-reload (wrap-defaults #'routes api-defaults)))
(defn run-web-server []
(run-jetty http-handler {:port 10555 :join? false}))
When I try this curl request
curl -X POST -H "Content-Type: application/json" http://localhost:10555/api/v1/echo -d '{"hello": "world"}'
I get this response
{:ssl-client-cert nil, :remote-addr "0:0:0:0:0:0:0:1", :params {}, :route-params {}, :headers {"accept" "*/*", "user-agent" "curl/7.43.0", "content-type" "application/json", "content-length" "18", "host" "localhost:10555"}, :server-port 10555, :content-length 18, :form-params {}, :query-params {}, :content-type "application/json", :character-encoding nil, :uri "/api/v1/echo", :server-name "localhost", :query-string nil, :body #object[org.eclipse.jetty.server.HttpInput 0x4317e5fa "org.eclipse.jetty.server.HttpInput@4317e5fa"], :scheme :http, :request-method :post}%
What I'm expecting to see is {"hello", "world"}
somewhere in that response, but it's not there. I see there is :body HttpInput
, but when I try (prn (-> req :body .read))
it outputs 123
. Because (= "{\"hello\", \"world\"}" 123) => false
, I'm a little lost about what to try next.
curl -X POST -H "Content-Type: application/x-www-form-urlencoded" http://localhost:10555/api/v1/echo -d "foo=1&bar=2"
does work as expected and returns :params {:foo "1", :bar "2"}
, but I'd rather submit json. I know I could use compojure-api probably, but I'm curious why this behaves this way.
Upvotes: 2
Views: 3123
Reputation: 13069
You need to use the ring-json middleware, particularly wrap-json-body
to parse json parameters:
The wrap-json-body middleware will parse the body of any request with a JSON content-type into a Clojure data structure, and assign it to the :body key.
This is the preferred way of handling JSON requests.
Upvotes: 6