I have a re-frame-based UI and try to communicate with my server using re-frame-http-fx. Sending and responding seems to work. However, I can't figure out how to parse the JSON body into a Clojure map on the server.
Here is my handler.clj
as minimal as I could get it:
(ns my.handler
(:require [compojure.core :refer [GET POST defroutes]]
[compojure.route :refer [resources]]
[ring.util.response :refer [resource-response]]
[ring.middleware.json :refer [wrap-json-response wrap-json-body]]))
(defn json-post [request]
(let [body (:body request)]
(prn body)
body))
(defroutes routes
(GET "/" [] (resource-response "index.html" {:root "public"}))
(POST "/post" request json-post)
(resources "/"))
(def handler (wrap-json-response (wrap-json-body routes {:keywords? true})))
As far as I understand, the wrap-json-body
middleware should replace the request body by a parsed version (a map?).
However, the output I get from (prn body)
in my json-post
handler is something like this:
#object[org.httpkit.BytesInputStream 0xda8b162 "BytesInputStream[len=41]"]
If I try something like (prn (:title body))
I get nil
(although the original map-turned-json-request contains :title
, as well as both the request and response body).
The request and response contain the correct json. The request Content-Type
is correctly set to application/json
(sent by re-frame-http-fx
). The length of the buffer (41) is also the correct body length as per request.
I am running out of things to try. Any ideas?
While investigating the issue further, I found my error that lead to the effect. It concerns the dev-handler
from the re-frame template that I conventiently omitted from my minimal example in the question.
I did not realize it was a problem, because the application seems to start fine even if you delete the entire definition of dev-handler
from handler.clj
, I assume because the server is initialized with handler
in server.clj
anyway (and the client does not fail fatally).
However, in project.clj
of the re-frame template, the following is configured for figwheel:
:figwheel {:css-dirs ["resources/public/css"]
:ring-handler my.handler/dev-handler}
This leads to middleware configured for handler
not being applied to my requests, thus not unwrapping the json body. Changing either the definition of dev-handler
(the the same as handler
in the question) or the configuration of figwheel in project.clj
(to point to handler
instead of dev-handler
) solves the problem.
If anybody knows the reasoning of different handlers in project.clj
and server.clj
, feel free to let me know.