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 запроса в более чем один хук НЕ используя атомы?

Решения, приходящие мне в голову:

  1. Оболочка промежуточного программного обеспечения, которая добавляет строковую версию body к ctx пары.
  2. Передать результат malformed? в post!...
  3. Используйте атомы.

Спасибо!

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))
Другие вопросы по тегам