多个 clojure-liberator 决策读取请求正文

Multiple clojure-liberator decisions reads request body

我有一个 defresource,它应该接受 POST-requests,在 :malformed-decision 中验证请求主体,在 :post!-decision 中将主体保存到数据库和 return :handle-created.

中保存的正文
(defn parse-project [context] (json/read-str
                               (slurp (get-in context [:request :body]))
                               :key-fn keyword))    
(defresource add-new-project
         :malformed? (fn[ctx] (not (project-is-valid (parse-project ctx))))
         :handle-malformed (fn [_] (generate-string (str "Malformed json!")))
         ...
         :post! (fn [ctx] (save-to-db (parse-project ctx))
         :handle-created  (fn [ctx] (... parse-project ...))

所以我的代码使用 slurp 函数读取了 ByteArrayInputStream(来自 :request :body)的三倍。第一次有效,但第二次调用 slurp 时,nil 作为参数传递并出现 java.io.EOFException: JSON 错误。我认为 reader 从上次离开的地方开始读取。

我怎么能读三遍请求正文?或者有什么好的方法可以将读取结果保存到变量并将其传递给其他解放者决策?

context 可以根据每个决策和操作函数的结果进行更新。您可以在 malformed? 和 return 地图中解析一次项目,解析后的项目将合并到上下文中,以便用于以下决策和操作。例如:

(defresource add-new-project
  :malformed? (fn[ctx] (let [project (parse-project ctx)]
                         (when (project-is-valid project)
                           {:project project})))
  :handle-malformed (fn [_] (generate-string (str "Malformed json!")))
  :post! (fn [ctx] (save-to-db (:project ctx)))
  :handle-created (fn [ctx] (do-something (:project ctx))))

如果项目有效,:malformed? return 将合并到上下文中的 {:project project} 映射将用于下一个决策和操作。 如果项目无效,它将 return nil 因此在 :handle-malformed.

中继续执行

有关解放者执行模型的更多信息,请参阅https://clojure-liberator.github.io/liberator/doc/execution-model.html