我该如何在Ring中模拟一个JSON POST请求?

9
我正在使用Peridot - https://github.com/xeqi/peridot 测试我的应用程序,一切正常,直到我尝试使用JSON数据模拟POST请求:
(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")))

会导致IOException: stream closed

有更好的方式吗?

2个回答

11

简述:

(-> (session app)
    (request "/test/json"
             :request-method :post
             :content-type "application/json"
             :body (.getBytes "\"hello\"" "UTF-8")))
当peridot生成请求映射时,默认情况下,对于:post请求的content-type会设置为application/x-www-form-urlencoded。使用指定的app wrap-params(包括在compojure.handler/site中)将尝试读取:body以解析任何表单编码参数,然后json-post再次尝试读取:body。但是,InputStream被设计成只能读取一次,这会导致异常。
基本上有两种方法来解决这个问题:
  1. 移除compojure.handler/site
  2. 添加一个请求内容类型(如tldr中所做)

5
(require '[cheshire.core :as json])

(-> (session app)
    (request "/test/json"
             :request-method :post
             :content-type "application/json"
             :body (json/generate-string data))

无需调用 .getBytes,只需传递带有 :body 参数的 JSON 即可。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接