Clojure 如何拦截Compojure请求并基于测试执行它?

Clojure 如何拦截Compojure请求并基于测试执行它?,clojure,compojure,ring,Clojure,Compojure,Ring,我有一些路线 (defroutes some-routes (GET "one" [] one) (GET "two" [] two)) (defroutes other-routes (GET "three" [] three) (GET "four" [] four)) (defroutes more-routes (GET "five" [] five) (GET "six" [] six)) (def all-routes (routes a

我有一些路线

(defroutes some-routes
    (GET "one" [] one)
    (GET "two" [] two))

(defroutes other-routes
  (GET "three" [] three)
  (GET "four" [] four))

(defroutes more-routes
  (GET "five" [] five)
  (GET "six" [] six))


(def all-routes 
  (routes app-routes
          (-> some-routes session/wrap-session my-interceptor)
          (-> more-routes session/wrap-session my-other-interceptor)
          other-routes))
我想截取
一些路由
,但不截取
其他路由
,并根据请求执行测试(检查会话中是否存在密钥和其他内容)。我有不止一个
我的另一个拦截器
做同样的事情,但不同

所以我从这个开始:

(defn my-interceptor [handler]
    (fn [request]
      (prn (-> request :session :thing-key))
        (let [thing (-> request :session :thing-key-id)]
          (if (nil? thing)
            (-> (response "Not authenticated"))
            (handler request)))))
如果会话中设置了
:thing key
,这将允许访问处理程序

不幸的是,这并不能很好地处理多组路由。此检查应仅适用于
某些路线
,而不适用于
其他路线
。但在执行处理程序之前,我们不知道路由是否匹配。此时处理程序已经执行了。我可以将其重写为执行
handler
,然后仅在响应为非nil时执行检查,但这意味着我在检查auth之前已经执行了处理程序

我接着说,这说明了问题:

(defn add-app-version-header [handler]
  (fn [request]
    (let [resp (handler request)
      headers (:headers resp)]
      (assoc resp :headers 
        (assoc headers "X-APP-INFO" "MyTerifficApp Version 0.0.1-Alpha")))))
我该怎么做?我想要的是:

  • 在处理请求之前检查响应(和其他逻辑)的一种方法
  • 我可以应用于一大组routes的处理程序
  • 这不会应用于应用程序中的所有路线
  • 我将让不止一个这样的处理程序对会话执行不同类型的检查

我应该怎么做呢?

拥有单独的处理程序或中间件的方法是使用
compojure.core/routes
分解路由,并仅在需要的地方使用处理程序

在你的情况下,如果你把你的
其他路线
放在第一位,你的问题应该得到解决

例如:

(def app-routes
   (compojure.core/routes
       other-routes
       (-> some-routes
           session/wrap-session
           my-interceptor)))
记住compojure路由,您总是可以编写一个自定义的
defroutes
,仅当路由与请求匹配时才调用处理程序,这是

这样,如果您有多个条件处理程序,则不需要依赖于将这些路由放在合成的末尾

请注意,这种方法是在您希望保持路由处理代码干净的情况下使用的

如果你不想使用自己的
defroutes
,只需调用内部拦截器:

(defroutes routes
   (GET "/" request (interceptor request show-all))

(defn interceptor
  [request handler]

谢谢不过我有不止一种支票,所以我认为你的建议不适用,把非支票项目放在第一位?我会考虑你的第二个建议。老实说,我是新来的(对Clojure来说也是很新的)。我是否必须放弃我的
defroutes
并重新编写路由才能这样做?还有一些功能,例如,如果route是
def-
'ed,则
。这是否意味着从compojure中复制粘贴代码块,或者我是否遗漏了要点?嗯,您可以随时在route handler中调用处理程序,而不是在外部调用处理程序,将更新答案以显示。谢谢,最后一点现在解决了我的问题,在我学习compojure和ring的其他部分时,这足以让某些东西发挥作用。
(my-def-routes routes
    (GET "/" request (show-all request))
(defroutes routes
   (GET "/" request (interceptor request show-all))

(defn interceptor
  [request handler]