【问题标题】:Access to route params at middleware stage在中间件阶段访问路由参数
【发布时间】:2023-08-23 10:26:01
【问题描述】:

我正在尝试编写一个中间件,用于将请求中的所有字符串对象 id 转换为 ObjectId 对象。

我正在使用以下方法实现这一点:

(defn get-object-id
  [id]
  (when (and (string? id) (re-matches object-id-regex id))
    (ObjectId. id)))

(defn maybe-obj->object-id [obj]
  (or (get-object-id obj) obj))

(defn- convert-string->object-ids [obj]
  (cwalk/postwalk
    (partial pcommon/maybe-obj->object-id) obj))

(defn warp-params-string->objectid
  "convert strings to object ids"
  [handler]
  (fn [request]
    (handler (update-in request [:params] convert-string->object-ids))))

这适用于 json 的所有参数,请求参数等。但这不适用于路由参数,例如:fst 用于 url "/:fst"。我查看了 GET 宏,并且路由参数被注入到该宏的某处。但是,由于 GET/POST 等最后执行,我的中间件无权访问这些。任何优雅的方式来实现这一点。

【问题讨论】:

  • 也许将 (handler (update-in request ... 更改为 (update-in (request handler) ... 以便在返回的过程中而不是在返回的过程中获取参数?
  • @noisesmith 这无济于事,因为我在处理我的 GET 请求时需要这些对象。

标签: clojure routes params middleware compojure


【解决方案1】:

那些/:foo/:bar-style 参数由于 URI 上的模式匹配而被绑定,模式在各个路由的定义中指定。外层甚至不知道图案是什么样的。因此,实际上不可能将这些处理提升到中间件。

相反,您可以编写一个宏,例如 with-preprocessed-params,来包装您的路由处理程序的主体。如果它最终在许多处理程序中有用,您可以另外提供您自己的 GET & Co. 版本,委托给 Compojure 的宏,主体包裹在您的参数处理宏中。

如果您希望在中间件的更多层中使用此预处理的结果,这并不是一个很好的解决方案。在这种情况下,假设您愿意将匹配的实际 URI 路径段留给核心处理程序层,您可以在一个中间件中执行其他参数类型的预处理,然后使用您的 GET & Co. 变体来预处理仅路由参数。

【讨论】: