2014-03-05 31 views
0

我有一些路線。如何攔截Compojure請求並根據測試執行它?

(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"))))) 

我該怎麼辦呢?我要的是:

  • 檢查處理請求
  • 之前的響應(和其他一些邏輯),我可以適用於肥胖型路由集合的方式處理
  • 這ISN」牛逼適用於所有航線的應用
  • 我將有不止一個這樣的處理程序上的會話

我應該如何去這樣做做一個別樣的支票?

回答

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] 
+0

謝謝。我確實有不止一種支票,所以我認爲你的建議先把未檢查的項目放在首位不適用?我會研究你的第二個建議。 – Joe

+0

我會說實話,我是Ring的新手(對Clojure來說還是個新手)。爲了做到這一點,我將不得不放棄我的'defroutes'並重寫我的路由?還有一些功能,例如'if-route'是'def-''。這是否意味着複製粘貼的代碼塊或者我錯過了這一點? – Joe

+0

那麼,你可以隨時在你的路由處理程序中調用處理程序,而不是在外面,將更新答案顯示。 –