reitit/doc/ring/dynamic_extensions.md
Alexander Kiel a19849fe58 Make Map Destructuring of Namespaced Keys more Beautiful
It's possible to put the :keys keyword in the namespace of the keys one likes to
destructure. With that one can use symbols in the vector again. One advantage of
having symbols is, that Cursive grays them out if not used. I found two
occurrences of unused destructured keys.
2019-07-13 17:02:41 +03:00

55 lines
1.5 KiB
Markdown

# Dynamic Extensions
`ring-handler` injects the `Match` into a request and it can be extracted at runtime with `reitit.ring/get-match`. This can be used to build ad-hoc extensions to the system.
Example middleware to guard routes based on user roles:
```clj
(require '[reitit.ring :as ring])
(require '[clojure.set :as set])
(defn wrap-enforce-roles [handler]
(fn [{::keys [roles] :as request}]
(let [required (some-> request (ring/get-match) :data ::roles)]
(if (and (seq required) (not (set/subset? required roles)))
{:status 403, :body "forbidden"}
(handler request)))))
```
Mounted to an app via router data (affecting all routes):
```clj
(def handler (constantly {:status 200, :body "ok"}))
(def app
(ring/ring-handler
(ring/router
[["/api"
["/ping" handler]
["/admin" {::roles #{:admin}}
["/ping" handler]]]]
{:data {:middleware [wrap-enforce-roles]}})))
```
Anonymous access to public route:
```clj
(app {:request-method :get, :uri "/api/ping"})
; {:status 200, :body "ok"}
```
Anonymous access to guarded route:
```clj
(app {:request-method :get, :uri "/api/admin/ping"})
; {:status 403, :body "forbidden"}
```
Authorized access to guarded route:
```clj
(app {:request-method :get, :uri "/api/admin/ping", ::roles #{:admin}})
; {:status 200, :body "ok"}
```
Dynamic extensions are nice, but we can do much better. See [data-driven middleware](data_driven_middleware.md) and [compiling routes](compiling_middleware.md).