2015-04-30 4 views
0

Давайте предположим, что у меня есть конечная точка POST /endpoint, который принимает JSON в качестве входных данных:Clojure Освободитель: получить тело запроса дважды

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? по номеру ...
  3. Использование атомов.

Спасибо!

ответ

2

ОК, это было довольно легко, есть, конечно, оболочка, которая делает это ...

[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)) 
+0

Спасибо @ DanielCompton! – andrusieczko