reitit/doc/ring/dynamic_extensions.md

56 lines
1.5 KiB
Markdown
Raw Normal View History

2017-12-10 14:57:09 +00:00
# Dynamic Extensions
2017-09-18 05:30:03 +00:00
`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.
2017-09-18 05:30:03 +00:00
Example middleware to guard routes based on user roles:
```clj
2018-02-11 17:15:25 +00:00
(require '[reitit.ring :as ring])
2017-09-18 05:30:03 +00:00
(require '[clojure.set :as set])
(defn wrap-enforce-roles [handler]
(fn [{:keys [my-roles] :as request}]
2017-11-18 10:47:16 +00:00
(let [required (some-> request (ring/get-match) :data ::roles)]
(if (and (seq required) (not (set/subset? required my-roles)))
2017-09-18 05:30:03 +00:00
{:status 403, :body "forbidden"}
(handler request)))))
```
2019-01-27 20:11:47 +00:00
Mounted to an app via router data (affecting all routes):
2017-09-18 05:30:03 +00:00
```clj
(def handler (constantly {:status 200, :body "ok"}))
(def app
(ring/ring-handler
(ring/router
[["/api"
["/ping" handler]
["/admin" {::roles #{:admin}}
["/ping" handler]]]]
2017-11-18 10:47:16 +00:00
{:data {:middleware [wrap-enforce-roles]}})))
2017-09-18 05:30:03 +00:00
```
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", :my-roles #{:admin}})
2017-09-18 05:30:03 +00:00
; {:status 200, :body "ok"}
```
2018-02-11 17:15:25 +00:00
Dynamic extensions are nice, but we can do much better. See [data-driven middleware](data_driven_middleware.md) and [compiling routes](compiling_middleware.md).