Compojure Ring Middleware 如何使用中间件之外的值

Compojure Ring Middleware How To Use Value Outside of Middleware

我有一个简单的路由和中间件设置 compojure/swagger,它使用了一个环形中间件。

(POST "/worlds" [request]
      :body-params [name :- String]
      :header-params [token :- String]
      :middleware [wrap-api-auth]
      :summary "Creates a new world with 'name'"
      (ok (do-something-with-user)

(defn wrap-api-auth [handler]
  (fn [request]
    (let
      [token (get (:headers request) "token")
       user (db/get-user-by-token token)]
      (if user
        (handler request)     ; pass to wrapped handler
        (unauthorized {:error "unauthorized"})))))

这定义了一个具有一些基本身份验证的简单路由。在 header 参数中传递的令牌用于进行数据库查询,returns 一个用户并继续,或者 returns false 并失败。

我想要完成的是将返回的用户传回,以便我以后可以使用它。我没有任何运气,因为我真的不知道我会在哪里尝试将它添加到我以后可以访问它的地方。我已尝试使用 request assoc 它,但似乎我以后无法访问它。理想的情况是我能够将它传递给 do-something-with-user 函数。

使用 assoc 向请求添加一些数据应该完全可行。

您可以在 https://gist.github.com/ska2342/4567b02531ff611db6a1208ebd4316e6#file-gh-validation-clj-L124

找到一个示例,其中包含一些与我在生产中使用的代码非常接近的代码

本质上,中间件调用

(handler (assoc request
                :validation {:valid true
                             :validation valid?}))

因此对于您的情况,以下应该有效:

(handler (assoc request
                :user user))

如果我理解正确,你使用的解构语法来自 compojure-api. According to the example at https://github.com/metosin/compojure-api/wiki/Middleware 我会说通过 :middleware 键设置的中间件的行为与预期的一样,你应该能够提取:user 来自 request,最终在您的路线中结束。

因此,只需将 request 传递给 do-something-with-user 函数即可:

(POST "/worlds" request
      :body-params [name :- String]
      :header-params [token :- String]
      :middleware [wrap-api-auth]
      :summary "Creates a new world with 'name'"
      (ok (do-something-with-user request))

它应该包含您在中间件函数中 assoc 输入的 :user。请注意 request 周围缺少的括号,就像对此答案的评论中提到的那样。