我有一些路线。
(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))
我想拦截some-routes
但不拦截other-routes
并根据请求执行测试(检查会话中是否存在密钥以及其他一些内容)。我不止一个。 my-other-interceptor
做同样的事但不同。
所以我从这开始:
(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
,这将允许访问处理程序。
不幸的是,这不适合拥有多套路线。此检查仅适用于some-routes
而非other-routes
。但是在我们执行处理程序之前,我们不知道路由是否匹配。此时处理程序已经执行了。我可以重写它来执行handler
然后只检查响应是否为非零,但这意味着我在检查auth之前执行了一个处理程序。
我跟着this example,显示了问题:
(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")))))
我该怎么做?我想要的是:
我该怎么做呢?
答案 0 :(得分:1)
使用单独的处理程序或中间件的方法是使用compojure.core/routes
分解路由,并仅在需要时使用处理程序。
在您的情况下,如果您先放置other-routes
,则应解决您的问题。
如:
(def app-routes
(compojure.core/routes
other-routes
(-> some-routes
session/wrap-session
my-interceptor)))
记住compojure路由are just ring handlers,您始终可以编写一个自定义defroutes
,仅当路由与请求匹配时才调用您的处理程序,这是make route source code
(defn make-route
"Returns a function that will only call the handler if the method and Clout
route match the request."
[method route handler]
(if-method method
(if-route route
(fn [request]
(render (handler request) request)))))
这样,如果您有多个条件处理程序,则不需要依赖于将这些路径放在合成的末尾。
请注意,如果您希望保持路线处理代码清洁,则采用这种方法。
(my-def-routes routes
(GET "/" request (show-all request))
如果您不想自己动作defroutes
,只需在内部调用拦截器:
(defroutes routes
(GET "/" request (interceptor request show-all))
(defn interceptor
[request handler]