mirror of
https://github.com/metosin/reitit.git
synced 2026-02-02 10:40:34 +00:00
Merge branch 'master' into html5-hist-fragments
This commit is contained in:
commit
f0fef3e525
27 changed files with 121 additions and 78 deletions
|
|
@ -539,7 +539,7 @@ We use [Break Versioning][breakver]. The version numbers follow a `<major>.<mino
|
||||||
(fn [request]
|
(fn [request]
|
||||||
(handler (update request ::acc (fnil conj []) id))))
|
(handler (update request ::acc (fnil conj []) id))))
|
||||||
|
|
||||||
(defn handler [{:keys [::acc]}]
|
(defn handler [{::keys [acc]}]
|
||||||
{:status 200, :body (conj acc :handler)})
|
{:status 200, :body (conj acc :handler)})
|
||||||
|
|
||||||
(def app
|
(def app
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,31 @@ request to the server. This means the URL will look normal, but the downside is
|
||||||
that the server must respond to all routes with correct file (`index.html`).
|
that the server must respond to all routes with correct file (`index.html`).
|
||||||
Check examples for simple Ring handler example.
|
Check examples for simple Ring handler example.
|
||||||
|
|
||||||
|
### Anchor click handling
|
||||||
|
|
||||||
|
HTML5 History router will handle click events on anchors where the href
|
||||||
|
matches the route tree (and other [rules](../../modules/reitit-frontend/src/reitit/frontend/history.cljs#L84-L98)).
|
||||||
|
If you have need to control this logic, for example to handle some
|
||||||
|
anchor clicks where the href matches route tree normally (i.e. browser load)
|
||||||
|
you can provide `:ignore-anchor-click?` function to add your own logic to
|
||||||
|
event handling:
|
||||||
|
|
||||||
|
```clj
|
||||||
|
(rfe/start!
|
||||||
|
router
|
||||||
|
{:use-fragment false
|
||||||
|
:ignore-anchor-click? (fn [router e el uri]
|
||||||
|
;; Add additional check on top of the default checks
|
||||||
|
(and (rfh/ignore-anchor-click? router e el uri)
|
||||||
|
(not= "false" (gobj/get (.-dataset el) "reititHandleClick"))))})
|
||||||
|
|
||||||
|
;; Use data-reitit-handle-click to disable Reitit anchor handling
|
||||||
|
[:a
|
||||||
|
{:href (rfe/href ::about)
|
||||||
|
:data-reitit-handle-click false}
|
||||||
|
"About"]
|
||||||
|
```
|
||||||
|
|
||||||
## Easy
|
## Easy
|
||||||
|
|
||||||
Reitit frontend routers require storing the state somewhere and passing it to
|
Reitit frontend routers require storing the state somewhere and passing it to
|
||||||
|
|
|
||||||
|
|
@ -17,10 +17,10 @@ controller identity
|
||||||
* `start` & `stop` functions, which are called with controller identity
|
* `start` & `stop` functions, which are called with controller identity
|
||||||
|
|
||||||
When you navigate to a route that has a controller, controller identity
|
When you navigate to a route that has a controller, controller identity
|
||||||
is first resolved by calling `identity` function, or by using `parameters`
|
is first resolved by using `parameters` declaration, or by calling `identity` function,
|
||||||
declaration, or if neither is set, the identity is `nil`. Next controller
|
or if neither is set, the identity is `nil`. Next, the controller
|
||||||
is initialized by calling `start` is called with the identity value.
|
is initialized by calling `start` with the controller identity value.
|
||||||
When you exit that route, `stop` is called with the return value of `params.`
|
When you exit that route, `stop` is called with the last controller identity value.
|
||||||
|
|
||||||
If you navigate to the same route with different match, identity gets
|
If you navigate to the same route with different match, identity gets
|
||||||
resolved again. If the identity changes from the previous value, controller
|
resolved again. If the identity changes from the previous value, controller
|
||||||
|
|
|
||||||
|
|
@ -66,7 +66,7 @@ The following produce identical middleware runtime function.
|
||||||
```clj
|
```clj
|
||||||
(require '[reitit.ring :as ring])
|
(require '[reitit.ring :as ring])
|
||||||
|
|
||||||
(defn handler [{:keys [::acc]}]
|
(defn handler [{::keys [acc]}]
|
||||||
{:status 200, :body (conj acc :handler)})
|
{:status 200, :body (conj acc :handler)})
|
||||||
|
|
||||||
(def app
|
(def app
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ Example middleware to guard routes based on user roles:
|
||||||
(require '[clojure.set :as set])
|
(require '[clojure.set :as set])
|
||||||
|
|
||||||
(defn wrap-enforce-roles [handler]
|
(defn wrap-enforce-roles [handler]
|
||||||
(fn [{:keys [::roles] :as request}]
|
(fn [{::keys [roles] :as request}]
|
||||||
(let [required (some-> request (ring/get-match) :data ::roles)]
|
(let [required (some-> request (ring/get-match) :data ::roles)]
|
||||||
(if (and (seq required) (not (set/subset? required roles)))
|
(if (and (seq required) (not (set/subset? required roles)))
|
||||||
{:status 403, :body "forbidden"}
|
{:status 403, :body "forbidden"}
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ Below is an example how to do reverse routing from a ring handler:
|
||||||
(ring/ring-handler
|
(ring/ring-handler
|
||||||
(ring/router
|
(ring/router
|
||||||
[["/users"
|
[["/users"
|
||||||
{:get (fn [{:keys [::r/router]}]
|
{:get (fn [{::r/keys [router]}]
|
||||||
{:status 200
|
{:status 200
|
||||||
:body (for [i (range 10)]
|
:body (for [i (range 10)]
|
||||||
{:uri (-> router
|
{:uri (-> router
|
||||||
|
|
|
||||||
|
|
@ -155,7 +155,7 @@ A middleware and a handler:
|
||||||
(fn [request]
|
(fn [request]
|
||||||
(handler (update request ::acc (fnil conj []) id))))
|
(handler (update request ::acc (fnil conj []) id))))
|
||||||
|
|
||||||
(defn handler [{:keys [::acc]}]
|
(defn handler [{::keys [acc]}]
|
||||||
{:status 200, :body (conj acc :handler)})
|
{:status 200, :body (conj acc :handler)})
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -155,7 +155,7 @@ Let's reuse the `wrap-enforce-roles` from [Dynamic extensions](dynamic_extension
|
||||||
(s/def ::roles (s/coll-of ::role :into #{}))
|
(s/def ::roles (s/coll-of ::role :into #{}))
|
||||||
|
|
||||||
(defn wrap-enforce-roles [handler]
|
(defn wrap-enforce-roles [handler]
|
||||||
(fn [{:keys [::roles] :as request}]
|
(fn [{::keys [roles] :as request}]
|
||||||
(let [required (some-> request (ring/get-match) :data ::roles)]
|
(let [required (some-> request (ring/get-match) :data ::roles)]
|
||||||
(if (and (seq required) (not (set/subset? required roles)))
|
(if (and (seq required) (not (set/subset? required roles)))
|
||||||
{:status 403, :body "forbidden"}
|
{:status 403, :body "forbidden"}
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ There is an extra option in ring-router (actually, in the underlying middleware-
|
||||||
(fn [request]
|
(fn [request]
|
||||||
(handler (update request ::acc (fnil conj []) id))))
|
(handler (update request ::acc (fnil conj []) id))))
|
||||||
|
|
||||||
(defn handler [{:keys [::acc]}]
|
(defn handler [{::keys [acc]}]
|
||||||
{:status 200, :body (conj acc :handler)})
|
{:status 200, :body (conj acc :handler)})
|
||||||
|
|
||||||
(def app
|
(def app
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@
|
||||||
|
|
||||||
(re-frame/reg-event-fx
|
(re-frame/reg-event-fx
|
||||||
::navigate
|
::navigate
|
||||||
(fn [db [_ route]]
|
(fn [db [_ & route]]
|
||||||
;; See `navigate` effect in routes.cljs
|
;; See `navigate` effect in routes.cljs
|
||||||
{::navigate! route}))
|
{::navigate! route}))
|
||||||
|
|
||||||
|
|
@ -59,8 +59,8 @@
|
||||||
;; Triggering navigation from events.
|
;; Triggering navigation from events.
|
||||||
(re-frame/reg-fx
|
(re-frame/reg-fx
|
||||||
::navigate!
|
::navigate!
|
||||||
(fn [k params query]
|
(fn [route]
|
||||||
(rfe/push-state k params query)))
|
(apply rfe/push-state route)))
|
||||||
|
|
||||||
;;; Routes ;;;
|
;;; Routes ;;;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,6 @@
|
||||||
:description "Reitit Http App with Swagger"
|
:description "Reitit Http App with Swagger"
|
||||||
:dependencies [[org.clojure/clojure "1.10.0"]
|
:dependencies [[org.clojure/clojure "1.10.0"]
|
||||||
[ring/ring-jetty-adapter "1.7.1"]
|
[ring/ring-jetty-adapter "1.7.1"]
|
||||||
[aleph "0.4.6"]
|
[aleph "0.4.7-alpha5"]
|
||||||
[metosin/reitit "0.3.9"]]
|
[metosin/reitit "0.3.9"]]
|
||||||
:repl-options {:init-ns example.server})
|
:repl-options {:init-ns example.server})
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@
|
||||||
[reitit.http.spec :as spec]
|
[reitit.http.spec :as spec]
|
||||||
[spec-tools.spell :as spell]
|
[spec-tools.spell :as spell]
|
||||||
[ring.adapter.jetty :as jetty]
|
[ring.adapter.jetty :as jetty]
|
||||||
[aleph.http :as client]
|
[aleph.http :as aleph]
|
||||||
[muuntaja.core :as m]
|
[muuntaja.core :as m]
|
||||||
[clojure.java.io :as io]
|
[clojure.java.io :as io]
|
||||||
[clojure.spec.alpha :as s]
|
[clojure.spec.alpha :as s]
|
||||||
|
|
@ -71,7 +71,7 @@
|
||||||
:responses {200 {:body any?}}
|
:responses {200 {:body any?}}
|
||||||
:handler (fn [{{{:keys [seed results]} :query} :parameters}]
|
:handler (fn [{{{:keys [seed results]} :query} :parameters}]
|
||||||
(d/chain
|
(d/chain
|
||||||
(client/get
|
(aleph/get
|
||||||
"https://randomuser.me/api/"
|
"https://randomuser.me/api/"
|
||||||
{:query-params {:seed seed, :results results}})
|
{:query-params {:seed seed, :results results}})
|
||||||
:body
|
:body
|
||||||
|
|
@ -146,6 +146,7 @@
|
||||||
|
|
||||||
(defn start []
|
(defn start []
|
||||||
(jetty/run-jetty #'app {:port 3000, :join? false, :async true})
|
(jetty/run-jetty #'app {:port 3000, :join? false, :async true})
|
||||||
|
;(aleph/start-server (aleph/wrap-ring-async-handler #'app) {:port 3000})
|
||||||
(println "server running in port 3000"))
|
(println "server running in port 3000"))
|
||||||
|
|
||||||
(comment
|
(comment
|
||||||
|
|
|
||||||
|
|
@ -4,4 +4,4 @@
|
||||||
[ring/ring-jetty-adapter "1.7.1"]
|
[ring/ring-jetty-adapter "1.7.1"]
|
||||||
[metosin/reitit "0.3.9"]]
|
[metosin/reitit "0.3.9"]]
|
||||||
:repl-options {:init-ns example.server}
|
:repl-options {:init-ns example.server}
|
||||||
:profiles{:dev {:dependencies [[ring/ring-mock "0.3.2"]]}})
|
:profiles {:dev {:dependencies [[ring/ring-mock "0.3.2"]]}})
|
||||||
|
|
|
||||||
|
|
@ -70,7 +70,7 @@
|
||||||
(-> request :muuntaja/request :format))
|
(-> request :muuntaja/request :format))
|
||||||
|
|
||||||
;; TODO: support faster key walking, walk/keywordize-keys is quite slow...
|
;; TODO: support faster key walking, walk/keywordize-keys is quite slow...
|
||||||
(defn request-coercer [coercion type model {:keys [::extract-request-format ::parameter-coercion]
|
(defn request-coercer [coercion type model {::keys [extract-request-format parameter-coercion]
|
||||||
:or {extract-request-format extract-request-format-default
|
:or {extract-request-format extract-request-format-default
|
||||||
parameter-coercion default-parameter-coercion}}]
|
parameter-coercion default-parameter-coercion}}]
|
||||||
(if coercion
|
(if coercion
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,7 @@
|
||||||
|
|
||||||
#?(:clj clojure.lang.Keyword
|
#?(:clj clojure.lang.Keyword
|
||||||
:cljs cljs.core.Keyword)
|
:cljs cljs.core.Keyword)
|
||||||
(into-interceptor [this data {:keys [::registry] :as opts}]
|
(into-interceptor [this data {::keys [registry] :as opts}]
|
||||||
(if-let [interceptor (if registry (registry this))]
|
(if-let [interceptor (if registry (registry this))]
|
||||||
(into-interceptor interceptor data opts)
|
(into-interceptor interceptor data opts)
|
||||||
(throw
|
(throw
|
||||||
|
|
@ -108,7 +108,7 @@
|
||||||
(chain interceptors nil nil))
|
(chain interceptors nil nil))
|
||||||
([interceptors data]
|
([interceptors data]
|
||||||
(chain interceptors data nil))
|
(chain interceptors data nil))
|
||||||
([interceptors data {:keys [::transform] :or {transform identity} :as opts}]
|
([interceptors data {::keys [transform] :or {transform identity} :as opts}]
|
||||||
(let [transform (if (vector? transform) (apply comp (reverse transform)) transform)]
|
(let [transform (if (vector? transform) (apply comp (reverse transform)) transform)]
|
||||||
(->> interceptors
|
(->> interceptors
|
||||||
(keep #(into-interceptor % data opts))
|
(keep #(into-interceptor % data opts))
|
||||||
|
|
@ -119,7 +119,7 @@
|
||||||
(defn compile-result
|
(defn compile-result
|
||||||
([route opts]
|
([route opts]
|
||||||
(compile-result route opts nil))
|
(compile-result route opts nil))
|
||||||
([[_ {:keys [interceptors handler] :as data}] {:keys [::queue] :as opts} _]
|
([[_ {:keys [interceptors handler] :as data}] {::keys [queue] :as opts} _]
|
||||||
(let [chain (chain (into (vec interceptors) [handler]) data opts)]
|
(let [chain (chain (into (vec interceptors) [handler]) data opts)]
|
||||||
(map->Endpoint
|
(map->Endpoint
|
||||||
{:interceptors chain
|
{:interceptors chain
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@
|
||||||
|
|
||||||
#?(:clj clojure.lang.Keyword
|
#?(:clj clojure.lang.Keyword
|
||||||
:cljs cljs.core.Keyword)
|
:cljs cljs.core.Keyword)
|
||||||
(into-middleware [this data {:keys [::registry] :as opts}]
|
(into-middleware [this data {::keys [registry] :as opts}]
|
||||||
(if-let [middleware (if registry (registry this))]
|
(if-let [middleware (if registry (registry this))]
|
||||||
(into-middleware middleware data opts)
|
(into-middleware middleware data opts)
|
||||||
(throw
|
(throw
|
||||||
|
|
@ -83,7 +83,7 @@
|
||||||
(if scope {:scope scope})))))
|
(if scope {:scope scope})))))
|
||||||
|
|
||||||
(defn- expand-and-transform
|
(defn- expand-and-transform
|
||||||
[middleware data {:keys [::transform] :or {transform identity} :as opts}]
|
[middleware data {::keys [transform] :or {transform identity} :as opts}]
|
||||||
(let [transform (if (vector? transform) (apply comp (reverse transform)) transform)]
|
(let [transform (if (vector? transform) (apply comp (reverse transform)) transform)]
|
||||||
(->> middleware
|
(->> middleware
|
||||||
(keep #(into-middleware % data opts))
|
(keep #(into-middleware % data opts))
|
||||||
|
|
|
||||||
|
|
@ -123,7 +123,7 @@
|
||||||
(->Problem p nil d spec problems)))
|
(->Problem p nil d spec problems)))
|
||||||
(keep identity) (seq) (vec))))
|
(keep identity) (seq) (vec))))
|
||||||
|
|
||||||
(defn validate [routes {:keys [spec ::wrap] :or {spec ::default-data, wrap identity}}]
|
(defn validate [routes {:keys [spec] ::keys [wrap] :or {spec ::default-data, wrap identity}}]
|
||||||
(when-let [problems (validate-route-data routes wrap spec)]
|
(when-let [problems (validate-route-data routes wrap spec)]
|
||||||
(exception/fail!
|
(exception/fail!
|
||||||
::invalid-route-data
|
::invalid-route-data
|
||||||
|
|
|
||||||
|
|
@ -67,6 +67,29 @@
|
||||||
(first (.composedPath original-event))
|
(first (.composedPath original-event))
|
||||||
(.-target event))))
|
(.-target event))))
|
||||||
|
|
||||||
|
(defn ignore-anchor-click?
|
||||||
|
"Precicate to check if the anchor click event default action
|
||||||
|
should be ignored. This logic will ignore the event
|
||||||
|
if anchor href matches the route tree, and in this case
|
||||||
|
the page location is updated using History API."
|
||||||
|
[router e el uri]
|
||||||
|
(let [current-domain (if (exists? js/location)
|
||||||
|
(.getDomain (.parse Uri js/location)))]
|
||||||
|
(and (or (and (not (.hasScheme uri)) (not (.hasDomain uri)))
|
||||||
|
(= current-domain (.getDomain uri)))
|
||||||
|
(not (.-altKey e))
|
||||||
|
(not (.-ctrlKey e))
|
||||||
|
(not (.-metaKey e))
|
||||||
|
(not (.-shiftKey e))
|
||||||
|
(or (not (.hasAttribute el "target"))
|
||||||
|
(contains? #{"" "_self"} (.getAttribute el "target")))
|
||||||
|
;; Left button
|
||||||
|
(= 0 (.-button e))
|
||||||
|
;; isContentEditable property is inherited from parents,
|
||||||
|
;; so if the anchor is inside contenteditable div, the property will be true.
|
||||||
|
(not (.-isContentEditable el))
|
||||||
|
(reitit/match-by-path router (.getPath uri)))))
|
||||||
|
|
||||||
(defrecord Html5History [on-navigate router listen-key click-listen-key]
|
(defrecord Html5History [on-navigate router listen-key click-listen-key]
|
||||||
History
|
History
|
||||||
(-init [this]
|
(-init [this]
|
||||||
|
|
@ -74,39 +97,24 @@
|
||||||
(fn [e]
|
(fn [e]
|
||||||
(-on-navigate this (-get-path this)))
|
(-on-navigate this (-get-path this)))
|
||||||
|
|
||||||
current-domain
|
ignore-anchor-click-predicate (or (:ignore-anchor-click? this)
|
||||||
(if (exists? js/location)
|
ignore-anchor-click?)
|
||||||
(.getDomain (.parse Uri js/location)))
|
|
||||||
|
|
||||||
;; Prevent document load when clicking a elements, if the href points to URL that is part
|
;; Prevent document load when clicking a elements, if the href points to URL that is part
|
||||||
;; of the routing tree."
|
;; of the routing tree."
|
||||||
ignore-anchor-click
|
ignore-anchor-click (fn [e]
|
||||||
(fn ignore-anchor-click
|
;; Returns the next matching ancestor of event target
|
||||||
[e]
|
(when-let [el (closest-by-tag (event-target e) "a")]
|
||||||
;; Returns the next matching ancestor of event target
|
(let [uri (.parse Uri (.-href el))]
|
||||||
(when-let [el (closest-by-tag (event-target e) "a")]
|
(when (ignore-anchor-click-predicate router e el uri)
|
||||||
(let [uri (.parse Uri (.-href el))]
|
(.preventDefault e)
|
||||||
(when (and (or (and (not (.hasScheme uri)) (not (.hasDomain uri)))
|
(let [path (str (.getPath uri)
|
||||||
(= current-domain (.getDomain uri)))
|
(when (.hasQuery uri)
|
||||||
(not (.-altKey e))
|
(str "?" (.getQuery uri)))
|
||||||
(not (.-ctrlKey e))
|
(when (.hasFragment uri)
|
||||||
(not (.-metaKey e))
|
(str "#" (.getFragment uri))))]
|
||||||
(not (.-shiftKey e))
|
(.pushState js/window.history nil "" path)
|
||||||
(not (contains? #{"_blank" "self"} (.getAttribute el "target")))
|
(-on-navigate this path))))))]
|
||||||
;; Left button
|
|
||||||
(= 0 (.-button e))
|
|
||||||
;; isContentEditable property is inherited from parents,
|
|
||||||
;; so if the anchor is inside contenteditable div, the property will be true.
|
|
||||||
(not (.-isContentEditable el))
|
|
||||||
(reitit/match-by-path router (.getPath uri)))
|
|
||||||
(.preventDefault e)
|
|
||||||
(let [path (str (.getPath uri)
|
|
||||||
(when (.hasQuery uri)
|
|
||||||
(str "?" (.getQuery uri)))
|
|
||||||
(when (.hasFragment uri)
|
|
||||||
(str "#" (.getFragment uri))))]
|
|
||||||
(.pushState js/window.history nil "" path)
|
|
||||||
(-on-navigate this path))))))]
|
|
||||||
(-on-navigate this (-get-path this))
|
(-on-navigate this (-get-path this))
|
||||||
(assoc this
|
(assoc this
|
||||||
:listen-key (gevents/listen js/window goog.events.EventType.POPSTATE handler false)
|
:listen-key (gevents/listen js/window goog.events.EventType.POPSTATE handler false)
|
||||||
|
|
@ -135,15 +143,24 @@
|
||||||
- on-navigate Function to be called when route changes. Takes two parameters, ´match´ and ´history´ object.
|
- on-navigate Function to be called when route changes. Takes two parameters, ´match´ and ´history´ object.
|
||||||
|
|
||||||
Options:
|
Options:
|
||||||
- :use-fragment (default true) If true, onhashchange and location hash are used to store current route."
|
- :use-fragment (default true) If true, onhashchange and location hash are used to store current route.
|
||||||
|
|
||||||
|
Options (Html5History):
|
||||||
|
- :ignore-anchor-click? Function (router, event, anchor element, uri) which will be called to
|
||||||
|
check if the anchor click event should be ignored.
|
||||||
|
To extend built-in check, you can call `reitit.frontend.history/ignore-anchor-click?`
|
||||||
|
function, which will ignore clicks if the href matches route tree."
|
||||||
([router on-navigate]
|
([router on-navigate]
|
||||||
(start! router on-navigate nil))
|
(start! router on-navigate nil))
|
||||||
([router
|
([router
|
||||||
on-navigate
|
on-navigate
|
||||||
{:keys [use-fragment]
|
{:keys [use-fragment]
|
||||||
:or {use-fragment true}}]
|
:or {use-fragment true}
|
||||||
(let [opts {:router router
|
:as opts}]
|
||||||
:on-navigate on-navigate}]
|
(let [opts (-> opts
|
||||||
|
(dissoc :use-fragment)
|
||||||
|
(assoc :router router
|
||||||
|
:on-navigate on-navigate))]
|
||||||
(-init (if use-fragment
|
(-init (if use-fragment
|
||||||
(map->FragmentHistory opts)
|
(map->FragmentHistory opts)
|
||||||
(map->Html5History opts))))))
|
(map->Html5History opts))))))
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@
|
||||||
(update acc method expand opts)
|
(update acc method expand opts)
|
||||||
acc)) data ring/http-methods)])
|
acc)) data ring/http-methods)])
|
||||||
|
|
||||||
(defn compile-result [[path data] {:keys [::default-options-handler] :as opts}]
|
(defn compile-result [[path data] {::keys [default-options-handler] :as opts}]
|
||||||
(let [[top childs] (ring/group-keys data)
|
(let [[top childs] (ring/group-keys data)
|
||||||
childs (cond-> childs
|
childs (cond-> childs
|
||||||
(and (not (:options childs)) (not (:handler top)) default-options-handler)
|
(and (not (:options childs)) (not (:handler top)) default-options-handler)
|
||||||
|
|
@ -127,7 +127,7 @@
|
||||||
(dissoc :data) ; data is already merged into routes
|
(dissoc :data) ; data is already merged into routes
|
||||||
(cond-> (seq interceptors)
|
(cond-> (seq interceptors)
|
||||||
(update-in [:data :interceptors] (partial into (vec interceptors)))))
|
(update-in [:data :interceptors] (partial into (vec interceptors)))))
|
||||||
router (reitit.http/router (r/routes router) router-opts)
|
router (reitit.http/router (r/routes router) router-opts) ;; will re-compile the interceptors
|
||||||
enrich-request (ring/create-enrich-request inject-match? inject-router?)
|
enrich-request (ring/create-enrich-request inject-match? inject-router?)
|
||||||
enrich-default-request (ring/create-enrich-default-request inject-router?)]
|
enrich-default-request (ring/create-enrich-default-request inject-router?)]
|
||||||
(with-meta
|
(with-meta
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@
|
||||||
(update :request dissoc ::r/match ::r/router)))
|
(update :request dissoc ::r/match ::r/router)))
|
||||||
|
|
||||||
(defn- handle [name stage]
|
(defn- handle [name stage]
|
||||||
(fn [{:keys [::original ::previous] :as ctx}]
|
(fn [{::keys [previous] :as ctx}]
|
||||||
(let [current (polish ctx)
|
(let [current (polish ctx)
|
||||||
previous (polish previous)]
|
previous (polish previous)]
|
||||||
(printer/print-doc (diff-doc stage name previous current) printer)
|
(printer/print-doc (diff-doc stage name previous current) printer)
|
||||||
|
|
|
||||||
|
|
@ -18,13 +18,13 @@
|
||||||
(defn polish [request]
|
(defn polish [request]
|
||||||
(dissoc request ::r/match ::r/router ::original ::previous))
|
(dissoc request ::r/match ::r/router ::original ::previous))
|
||||||
|
|
||||||
(defn printed-request [name {:keys [::original ::previous] :as request}]
|
(defn printed-request [name {::keys [previous] :as request}]
|
||||||
(printer/print-doc (diff-doc :request name (polish previous) (polish request)) printer)
|
(printer/print-doc (diff-doc :request name (polish previous) (polish request)) printer)
|
||||||
(-> request
|
(-> request
|
||||||
(update ::original (fnil identity request))
|
(update ::original (fnil identity request))
|
||||||
(assoc ::previous request)))
|
(assoc ::previous request)))
|
||||||
|
|
||||||
(defn printed-response [name {:keys [::original ::previous] :as response}]
|
(defn printed-response [name {::keys [previous] :as response}]
|
||||||
(printer/print-doc (diff-doc :response name (polish previous) (polish response)) printer)
|
(printer/print-doc (diff-doc :response name (polish previous) (polish response)) printer)
|
||||||
(-> response
|
(-> response
|
||||||
(update ::original (fnil identity response))
|
(update ::original (fnil identity response))
|
||||||
|
|
|
||||||
|
|
@ -49,7 +49,7 @@
|
||||||
Executor
|
Executor
|
||||||
(queue [_ interceptors]
|
(queue [_ interceptors]
|
||||||
(->> interceptors
|
(->> interceptors
|
||||||
(map (fn [{:keys [::interceptor/handler] :as interceptor}]
|
(map (fn [{::interceptor/keys [handler] :as interceptor}]
|
||||||
(or handler interceptor)))
|
(or handler interceptor)))
|
||||||
(keep ->interceptor)))
|
(keep ->interceptor)))
|
||||||
(enqueue [_ context interceptors]
|
(enqueue [_ context interceptors]
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@
|
||||||
(update acc method expand opts)
|
(update acc method expand opts)
|
||||||
acc)) data http-methods)])
|
acc)) data http-methods)])
|
||||||
|
|
||||||
(defn compile-result [[path data] {:keys [::default-options-handler] :as opts}]
|
(defn compile-result [[path data] {::keys [default-options-handler] :as opts}]
|
||||||
(let [[top childs] (group-keys data)
|
(let [[top childs] (group-keys data)
|
||||||
childs (cond-> childs
|
childs (cond-> childs
|
||||||
(and (not (:options childs)) (not (:handler top)) default-options-handler)
|
(and (not (:options childs)) (not (:handler top)) default-options-handler)
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@
|
||||||
(queue [_ interceptors]
|
(queue [_ interceptors]
|
||||||
(queue/into-queue
|
(queue/into-queue
|
||||||
(map
|
(map
|
||||||
(fn [{:keys [::interceptor/handler] :as interceptor}]
|
(fn [{::interceptor/keys [handler] :as interceptor}]
|
||||||
(or handler interceptor))
|
(or handler interceptor))
|
||||||
interceptors)))
|
interceptors)))
|
||||||
(execute [_ interceptors request]
|
(execute [_ interceptors request]
|
||||||
|
|
|
||||||
|
|
@ -71,7 +71,7 @@
|
||||||
"Create a ring handler to emit swagger spec. Collects all routes from router which have
|
"Create a ring handler to emit swagger spec. Collects all routes from router which have
|
||||||
an intersecting `[:swagger :id]` and which are not marked with `:no-doc` route data."
|
an intersecting `[:swagger :id]` and which are not marked with `:no-doc` route data."
|
||||||
(fn create-swagger
|
(fn create-swagger
|
||||||
([{:keys [::r/router ::r/match :request-method]}]
|
([{::r/keys [router match] :keys [request-method]}]
|
||||||
(let [{:keys [id] :or {id ::default} :as swagger} (-> match :result request-method :data :swagger)
|
(let [{:keys [id] :or {id ::default} :as swagger} (-> match :result request-method :data :swagger)
|
||||||
ids (trie/into-set id)
|
ids (trie/into-set id)
|
||||||
strip-top-level-keys #(dissoc % :id :info :host :basePath :definitions :securityDefinitions)
|
strip-top-level-keys #(dissoc % :id :info :host :basePath :definitions :securityDefinitions)
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@
|
||||||
(defn interceptor [name]
|
(defn interceptor [name]
|
||||||
{:enter (fn [ctx] (update-in ctx [:request ::i] (fnil conj []) name))})
|
{:enter (fn [ctx] (update-in ctx [:request ::i] (fnil conj []) name))})
|
||||||
|
|
||||||
(defn handler [{:keys [::i]}]
|
(defn handler [{::keys [i]}]
|
||||||
{:status 200 :body (conj i :ok)})
|
{:status 200 :body (conj i :ok)})
|
||||||
|
|
||||||
(deftest http-router-test
|
(deftest http-router-test
|
||||||
|
|
@ -89,7 +89,7 @@
|
||||||
(is (= name (-> (r/match-by-name router name) :data :name))))))))
|
(is (= name (-> (r/match-by-name router name) :data :name))))))))
|
||||||
|
|
||||||
(def enforce-roles-interceptor
|
(def enforce-roles-interceptor
|
||||||
{:enter (fn [{{:keys [::roles] :as request} :request :as ctx}]
|
{:enter (fn [{{::keys [roles] :as request} :request :as ctx}]
|
||||||
(let [required (some-> request (http/get-match) :data ::roles)]
|
(let [required (some-> request (http/get-match) :data ::roles)]
|
||||||
(if (and (seq required) (not (set/intersection required roles)))
|
(if (and (seq required) (not (set/intersection required roles)))
|
||||||
(-> ctx
|
(-> ctx
|
||||||
|
|
@ -280,7 +280,7 @@
|
||||||
(let [interceptor (fn [name] {:name name
|
(let [interceptor (fn [name] {:name name
|
||||||
:enter (fn [ctx]
|
:enter (fn [ctx]
|
||||||
(update-in ctx [:request ::i] (fnil conj []) name))})
|
(update-in ctx [:request ::i] (fnil conj []) name))})
|
||||||
handler (fn [{:keys [::i]}] {:status 200 :body (conj i :ok)})
|
handler (fn [{::keys [i]}] {:status 200 :body (conj i :ok)})
|
||||||
request {:uri "/api/avaruus" :request-method :get}
|
request {:uri "/api/avaruus" :request-method :get}
|
||||||
create (fn [options]
|
create (fn [options]
|
||||||
(http/ring-handler
|
(http/ring-handler
|
||||||
|
|
@ -492,14 +492,14 @@
|
||||||
(testing "1-arity"
|
(testing "1-arity"
|
||||||
((http/ring-handler
|
((http/ring-handler
|
||||||
(http/router [])
|
(http/router [])
|
||||||
(fn [{:keys [::r/router]}]
|
(fn [{::r/keys [router]}]
|
||||||
(is router))
|
(is router))
|
||||||
{:executor sieppari/executor})
|
{:executor sieppari/executor})
|
||||||
{}))
|
{}))
|
||||||
(testing "3-arity"
|
(testing "3-arity"
|
||||||
((http/ring-handler
|
((http/ring-handler
|
||||||
(http/router [])
|
(http/router [])
|
||||||
(fn [{:keys [::r/router]}]
|
(fn [{::r/keys [router]}]
|
||||||
(is router))
|
(is router))
|
||||||
{:executor sieppari/executor})
|
{:executor sieppari/executor})
|
||||||
{} ::respond ::raise)))
|
{} ::respond ::raise)))
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@
|
||||||
(mw handler (keyword (str name "_" name2 "_" name3))))
|
(mw handler (keyword (str name "_" name2 "_" name3))))
|
||||||
|
|
||||||
(defn handler
|
(defn handler
|
||||||
([{:keys [::mw]}]
|
([{::keys [mw]}]
|
||||||
{:status 200 :body (conj mw :ok)})
|
{:status 200 :body (conj mw :ok)})
|
||||||
([request respond _]
|
([request respond _]
|
||||||
(respond (handler request))))
|
(respond (handler request))))
|
||||||
|
|
@ -119,7 +119,7 @@
|
||||||
(is (= name (-> (r/match-by-name router name) :data :name))))))))
|
(is (= name (-> (r/match-by-name router name) :data :name))))))))
|
||||||
|
|
||||||
(defn wrap-enforce-roles [handler]
|
(defn wrap-enforce-roles [handler]
|
||||||
(fn [{:keys [::roles] :as request}]
|
(fn [{::keys [roles] :as request}]
|
||||||
(let [required (some-> request (ring/get-match) :data ::roles)]
|
(let [required (some-> request (ring/get-match) :data ::roles)]
|
||||||
(if (and (seq required) (not (set/intersection required roles)))
|
(if (and (seq required) (not (set/intersection required roles)))
|
||||||
{:status 403, :body "forbidden"}
|
{:status 403, :body "forbidden"}
|
||||||
|
|
@ -399,7 +399,7 @@
|
||||||
:wrap (fn [handler]
|
:wrap (fn [handler]
|
||||||
(fn [request]
|
(fn [request]
|
||||||
(handler (update request ::mw (fnil conj []) name))))})
|
(handler (update request ::mw (fnil conj []) name))))})
|
||||||
handler (fn [{:keys [::mw]}] {:status 200 :body (conj mw :ok)})
|
handler (fn [{::keys [mw]}] {:status 200 :body (conj mw :ok)})
|
||||||
request {:uri "/api/avaruus" :request-method :get}
|
request {:uri "/api/avaruus" :request-method :get}
|
||||||
create (fn [options]
|
create (fn [options]
|
||||||
(ring/ring-handler
|
(ring/ring-handler
|
||||||
|
|
@ -583,13 +583,13 @@
|
||||||
(testing "1-arity"
|
(testing "1-arity"
|
||||||
((ring/ring-handler
|
((ring/ring-handler
|
||||||
(ring/router [])
|
(ring/router [])
|
||||||
(fn [{:keys [::r/router]}]
|
(fn [{::r/keys [router]}]
|
||||||
(is router)))
|
(is router)))
|
||||||
{}))
|
{}))
|
||||||
(testing "3-arity"
|
(testing "3-arity"
|
||||||
((ring/ring-handler
|
((ring/ring-handler
|
||||||
(ring/router [])
|
(ring/router [])
|
||||||
(fn [{:keys [::r/router]} _ _]
|
(fn [{::r/keys [router]} _ _]
|
||||||
(is router)))
|
(is router)))
|
||||||
{} ::respond ::raise)))
|
{} ::respond ::raise)))
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue