问题
I'm using peridot - https://github.com/xeqi/peridot to test my ring application, and its working fine until I try to mock a post request with json data:
(require '[cheshire.core :as json]) (use 'compojure.core) (defn json-post [req] (if (:body req) (json/parse-string (slurp (:body req))))) (defroutes all-routes (POST "/test/json" req (json-response (json-post req)))) (def app (compojure.handler/site all-routes)) (use 'peridot.core) (-> (session app) (request "/test/json" :request-method :post :body (java.io.ByteArrayInputStream. (.getBytes "hello" "UTF-8")))
gives IOException: stream closed
.
Is there a better way to do this?
回答1:
tldr:
(-> (session app)
(request "/test/json"
:request-method :post
:content-type "application/json"
:body (.getBytes "\"hello\"" "UTF-8")))
When peridot generates a request map it will default to application/x-www-form-urlencoded
for the content-type for a :post
request. With the app as specified wrap-params
(which is included by compojure.handler/site
) will attempt to read the :body
in order to parse any form-urlencoded parameters. Then json-post
attempts to read the :body
again. However InputStream
s are designed to be read once, and that causes the exception.
There are basically two ways to solve the issue:
- Remove
compojure.handler/site
. - Add a content type to the request (as done in the tldr)
回答2:
(require '[cheshire.core :as json])
(-> (session app)
(request "/test/json"
:request-method :post
:content-type "application/json"
:body (json/generate-string data))
No need to call .getBytes
, just pass json with :body
parameter.
来源:https://stackoverflow.com/questions/17035319/how-do-i-mock-a-json-post-request-in-ring