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)})))

所以我的意图是:

这里的问题是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. 使用原子。

谢谢!

好的,这很简单,当然有一个包装器可以做到这一点...

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