From 158695d47b484d28c0331f21d0c1de3acd7ab065 Mon Sep 17 00:00:00 2001 From: Tommi Reiman Date: Sat, 22 Sep 2018 17:21:25 +0300 Subject: [PATCH] Support for top-level middleware in reitit-ring See #143 --- modules/reitit-ring/src/reitit/ring.cljc | 68 +++++++++++++----------- test/cljc/reitit/ring_test.cljc | 16 ++++++ 2 files changed, 53 insertions(+), 31 deletions(-) diff --git a/modules/reitit-ring/src/reitit/ring.cljc b/modules/reitit-ring/src/reitit/ring.cljc index f74b0e85a..3b08e1130 100644 --- a/modules/reitit-ring/src/reitit/ring.cljc +++ b/modules/reitit-ring/src/reitit/ring.cljc @@ -177,41 +177,47 @@ (create handler))))) (defn ring-handler - "Creates a ring-handler out of a ring-router. - Supports both 1 (sync) and 3 (async) arities. - Optionally takes a ring-handler which is called - in no route matches." + "Creates a ring-handler out of a router, optional default ring-handler + and options map, with the following keys: + + | key | description | + | --------------|-------------| + | `:middleware` | Optional sequence of middleware that are wrap the [[ring-handler]]" ([router] (ring-handler router nil)) ([router default-handler] - (let [default-handler (or default-handler (fn ([_]) ([_ respond _] (respond nil))))] + (ring-handler router default-handler nil)) + ([router default-handler {:keys [middleware]}] + (let [default-handler (or default-handler (fn ([_]) ([_ respond _] (respond nil)))) + wrap (if middleware (partial middleware/chain middleware) identity)] (with-meta - (fn - ([request] - (if-let [match (r/match-by-path router (:uri request))] - (let [method (:request-method request) - path-params (:path-params match) - result (:result match) - handler (-> result method :handler (or default-handler)) - request (-> request - (impl/fast-assoc :path-params path-params) - (impl/fast-assoc ::r/match match) - (impl/fast-assoc ::r/router router))] - (or (handler request) (default-handler request))) - (default-handler request))) - ([request respond raise] - (if-let [match (r/match-by-path router (:uri request))] - (let [method (:request-method request) - path-params (:path-params match) - result (:result match) - handler (-> result method :handler (or default-handler)) - request (-> request - (impl/fast-assoc :path-params path-params) - (impl/fast-assoc ::r/match match) - (impl/fast-assoc ::r/router router))] - ((routes handler default-handler) request respond raise)) - (default-handler request respond raise)) - nil)) + (wrap + (fn + ([request] + (if-let [match (r/match-by-path router (:uri request))] + (let [method (:request-method request) + path-params (:path-params match) + result (:result match) + handler (-> result method :handler (or default-handler)) + request (-> request + (impl/fast-assoc :path-params path-params) + (impl/fast-assoc ::r/match match) + (impl/fast-assoc ::r/router router))] + (or (handler request) (default-handler request))) + (default-handler request))) + ([request respond raise] + (if-let [match (r/match-by-path router (:uri request))] + (let [method (:request-method request) + path-params (:path-params match) + result (:result match) + handler (-> result method :handler (or default-handler)) + request (-> request + (impl/fast-assoc :path-params path-params) + (impl/fast-assoc ::r/match match) + (impl/fast-assoc ::r/router router))] + ((routes handler default-handler) request respond raise)) + (default-handler request respond raise)) + nil))) {::r/router router})))) (defn get-router [handler] diff --git a/test/cljc/reitit/ring_test.cljc b/test/cljc/reitit/ring_test.cljc index 60bdb2e4c..2038855d7 100644 --- a/test/cljc/reitit/ring_test.cljc +++ b/test/cljc/reitit/ring_test.cljc @@ -78,6 +78,22 @@ (is (= {:status 200, :body [:api :users :post :ok]} @result)))))) + (testing "with top-level middleware" + (let [router (ring/router + ["/api" {:middleware [[mw :api]]} + ["/get" {:get handler}]]) + app (ring/ring-handler router nil {:middleware [[mw :top]]})] + + (testing "router can be extracted" + (is (= router (ring/get-router app)))) + + (testing "not found" + (is (= nil (app {:uri "/favicon.ico"})))) + + (testing "on match" + (is (= {:status 200, :body [:top :api :ok]} + (app {:uri "/api/get" :request-method :get})))))) + (testing "named routes" (let [router (ring/router [["/api"