Clojure Liberator:两次获取请求正文
Clojure Liberator: get request body twice
假设我有一个端点 POST /endpoint
将 JSON 作为输入数据:
POST /endpoint
{
"resource": {
"name": "great"
}
}
现在,我想检查传入的JSON是否有效。我认为 :malformed?
钩子会是做这件事的好地方。
于是想出了这样一段代码:
(ANY "/endpoint" []
(resource
:allowed-methods [:post]
:available-media-types ["application/json"]
:malformed? (fn [ctx] (let [body (get-body-from-request ctx)
is-malformed (not (is-body-valid body))]
is-malformed)
:post! (fn [ctx] (let [body (get-body-from-request ctx)]
(create-an-object body)))
:handle-created (fn [ctx] {:method :post :body (:body @request)})))
所以我的意图是:
- 从请求中获取
body
,检查它是否有效 (is-body-valid
)
- 在
post!
钩子中,再次使用 body
并做真正的工作 (create-an-object
)
这里的问题是get-body-from-request
函数:
(defn get-body-from-request [ctx]
(json/read-str (slurp (get-in ctx [:request :body])) :key-fn keyword))
它工作得很好,但是 body
是一个 InputStream
,所以我只能读一次。
有没有一种方法可以在多个不使用原子的挂钩中使用 body
请求?
我想到的解决方案:
- 一个中间件包装器,将
body
的字符串版本添加到 ctx
参数。
- 将
malformed?
的结果传递给post!
...
- 使用原子。
谢谢!
好的,这很简单,当然有一个包装器可以做到这一点...
[ring-json-params "0.1.3"]
然后您只需包装您的应用程序处理程序:
(ns my.app
(:require [ring.middleware.json :refer [wrap-json-params]]))
(def app
(-> handler
(wrap-json-params)))
并且在您的 ctx
对象中您有一个 json-params
对象:
:malformed? (fn [ctx] (let [params (get-in ctx [:request :json-params])]
false))
假设我有一个端点 POST /endpoint
将 JSON 作为输入数据:
POST /endpoint
{
"resource": {
"name": "great"
}
}
现在,我想检查传入的JSON是否有效。我认为 :malformed?
钩子会是做这件事的好地方。
于是想出了这样一段代码:
(ANY "/endpoint" []
(resource
:allowed-methods [:post]
:available-media-types ["application/json"]
:malformed? (fn [ctx] (let [body (get-body-from-request ctx)
is-malformed (not (is-body-valid body))]
is-malformed)
:post! (fn [ctx] (let [body (get-body-from-request ctx)]
(create-an-object body)))
:handle-created (fn [ctx] {:method :post :body (:body @request)})))
所以我的意图是:
- 从请求中获取
body
,检查它是否有效 (is-body-valid
) - 在
post!
钩子中,再次使用body
并做真正的工作 (create-an-object
)
这里的问题是get-body-from-request
函数:
(defn get-body-from-request [ctx]
(json/read-str (slurp (get-in ctx [:request :body])) :key-fn keyword))
它工作得很好,但是 body
是一个 InputStream
,所以我只能读一次。
有没有一种方法可以在多个不使用原子的挂钩中使用 body
请求?
我想到的解决方案:
- 一个中间件包装器,将
body
的字符串版本添加到ctx
参数。 - 将
malformed?
的结果传递给post!
... - 使用原子。
谢谢!
好的,这很简单,当然有一个包装器可以做到这一点...
[ring-json-params "0.1.3"]
然后您只需包装您的应用程序处理程序:
(ns my.app
(:require [ring.middleware.json :refer [wrap-json-params]]))
(def app
(-> handler
(wrap-json-params)))
并且在您的 ctx
对象中您有一个 json-params
对象:
:malformed? (fn [ctx] (let [params (get-in ctx [:request :json-params])]
false))