mirror of
https://github.com/metosin/reitit.git
synced 2026-01-02 06:38:26 +00:00
Merge pull request #146 from metosin/top-level-mw
Support for top-level middleware
This commit is contained in:
commit
86eac2ff92
4 changed files with 97 additions and 31 deletions
29
CHANGELOG.md
29
CHANGELOG.md
|
|
@ -2,6 +2,35 @@
|
|||
|
||||
## `reitit-ring`
|
||||
|
||||
* `ring-handler` takes optionally a 3rd argument, an options map which can be used to se top-level middleware, applied before any routing is done:
|
||||
|
||||
```clj
|
||||
(require '[reitit.ring :as ring])
|
||||
|
||||
(defn wrap [handler id]
|
||||
(fn [request]
|
||||
(handler (update request ::acc (fnil conj []) id))))
|
||||
|
||||
(defn handler [{:keys [::acc]}]
|
||||
{:status 200, :body (conj acc :handler)})
|
||||
|
||||
(def app
|
||||
(ring/ring-handler
|
||||
(ring/router
|
||||
["/api" {:middleware [[mw :api]]}
|
||||
["/get" {:get handler}]])
|
||||
(ring/create-default-handler)
|
||||
{:middleware [[mw :top]]}))
|
||||
|
||||
(app {:request-method :get, :uri "/api/get"})
|
||||
; {:status 200, :body [:top :api :ok]}
|
||||
|
||||
(require '[reitit.core :as r])
|
||||
|
||||
(-> app (ring/get-router))
|
||||
; #object[reitit.core$single_static_path_router]
|
||||
```
|
||||
|
||||
* updated deps:
|
||||
|
||||
```clj
|
||||
|
|
|
|||
|
|
@ -127,6 +127,21 @@ Middleware is applied correctly:
|
|||
; {:status 200, :body [:api :admin :db :delete :handler]}
|
||||
```
|
||||
|
||||
Top-level middleware, applied before any routing is done:
|
||||
|
||||
```clj
|
||||
(def app
|
||||
(ring/ring-handler
|
||||
(ring/router
|
||||
["/api" {:middleware [[mw :api]]}
|
||||
["/get" {:get handler}]])
|
||||
nil
|
||||
{:middleware [[mw :top]]}))
|
||||
|
||||
(app {:request-method :get, :uri "/api/get"})
|
||||
; {:status 200, :body [:top :api :ok]}
|
||||
```
|
||||
|
||||
# Async Ring
|
||||
|
||||
All built-in middleware provide both 2 and 3-arity and are compiled for both Clojure & ClojureScript, so they work with [Async Ring](https://www.booleanknot.com/blog/2016/07/15/asynchronous-ring.html) and [Node.js](https://nodejs.org) too.
|
||||
|
|
|
|||
|
|
@ -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]
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
Loading…
Reference in a new issue