Clojure Liberator: получить тело запроса дважды
Давайте предположим, что у меня есть конечная точка 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!
... - Используйте атомы.
Спасибо!
1 ответ
ОК, это было довольно легко, конечно, есть обертка, которая делает это...
[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))