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

View file

@ -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"