Support for top-level middleware in reitit-ring

See #143
This commit is contained in:
Tommi Reiman 2018-09-22 17:21:25 +03:00
parent 75c5dc492c
commit 158695d47b
2 changed files with 53 additions and 31 deletions

View file

@ -177,41 +177,47 @@
(create handler))))) (create handler)))))
(defn ring-handler (defn ring-handler
"Creates a ring-handler out of a ring-router. "Creates a ring-handler out of a router, optional default ring-handler
Supports both 1 (sync) and 3 (async) arities. and options map, with the following keys:
Optionally takes a ring-handler which is called
in no route matches." | key | description |
| --------------|-------------|
| `:middleware` | Optional sequence of middleware that are wrap the [[ring-handler]]"
([router] ([router]
(ring-handler router nil)) (ring-handler router nil))
([router default-handler] ([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 (with-meta
(fn (wrap
([request] (fn
(if-let [match (r/match-by-path router (:uri request))] ([request]
(let [method (:request-method request) (if-let [match (r/match-by-path router (:uri request))]
path-params (:path-params match) (let [method (:request-method request)
result (:result match) path-params (:path-params match)
handler (-> result method :handler (or default-handler)) result (:result match)
request (-> request handler (-> result method :handler (or default-handler))
(impl/fast-assoc :path-params path-params) request (-> request
(impl/fast-assoc ::r/match match) (impl/fast-assoc :path-params path-params)
(impl/fast-assoc ::r/router router))] (impl/fast-assoc ::r/match match)
(or (handler request) (default-handler request))) (impl/fast-assoc ::r/router router))]
(default-handler request))) (or (handler request) (default-handler request)))
([request respond raise] (default-handler request)))
(if-let [match (r/match-by-path router (:uri request))] ([request respond raise]
(let [method (:request-method request) (if-let [match (r/match-by-path router (:uri request))]
path-params (:path-params match) (let [method (:request-method request)
result (:result match) path-params (:path-params match)
handler (-> result method :handler (or default-handler)) result (:result match)
request (-> request handler (-> result method :handler (or default-handler))
(impl/fast-assoc :path-params path-params) request (-> request
(impl/fast-assoc ::r/match match) (impl/fast-assoc :path-params path-params)
(impl/fast-assoc ::r/router router))] (impl/fast-assoc ::r/match match)
((routes handler default-handler) request respond raise)) (impl/fast-assoc ::r/router router))]
(default-handler request respond raise)) ((routes handler default-handler) request respond raise))
nil)) (default-handler request respond raise))
nil)))
{::r/router router})))) {::r/router router}))))
(defn get-router [handler] (defn get-router [handler]

View file

@ -78,6 +78,22 @@
(is (= {:status 200, :body [:api :users :post :ok]} (is (= {:status 200, :body [:api :users :post :ok]}
@result)))))) @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" (testing "named routes"
(let [router (ring/router (let [router (ring/router
[["/api" [["/api"