mirror of
https://github.com/metosin/reitit.git
synced 2025-12-18 17:01:11 +00:00
:inject-router? and :inject-match? for ring & http
This commit is contained in:
parent
80dea6cfef
commit
75c4f78f5d
3 changed files with 193 additions and 55 deletions
|
|
@ -73,12 +73,22 @@
|
|||
(r/router data opts))))
|
||||
|
||||
(defn routing-interceptor
|
||||
"A Pedestal-style routing interceptor that enqueus the interceptors into context."
|
||||
[router default-handler {:keys [interceptors executor]}]
|
||||
"Creates a Pedestal-style routing interceptor that enqueus the interceptors into context.
|
||||
Takes http-router, default ring-handler and and options map, with the following keys:
|
||||
|
||||
| key | description |
|
||||
| ------------------|-------------|
|
||||
| `:executor` | `reitit.interceptor.Executor` for the interceptor chain
|
||||
| `:interceptors` | Optional sequence of interceptors that are always run before any other interceptors, even for the default handler
|
||||
| `:inject-match?` | Boolean to inject `match` into request under `:reitit.core/match` key (default true)
|
||||
| `:inject-router?` | Boolean to inject `router` into request under `:reitit.core/router` key (default true)"
|
||||
[router default-handler {:keys [interceptors executor inject-match? inject-router?]
|
||||
:or {inject-match? true, inject-router? true}}]
|
||||
(let [default-handler (or default-handler (fn ([_])))
|
||||
default-interceptors (->> interceptors
|
||||
(map #(interceptor/into-interceptor % nil (r/options router))))
|
||||
default-queue (interceptor/queue executor default-interceptors)]
|
||||
default-queue (interceptor/queue executor default-interceptors)
|
||||
enrich-request (ring/create-enrich-request inject-match? inject-router?)]
|
||||
{:name ::router
|
||||
:enter (fn [{:keys [request] :as context}]
|
||||
(if-let [match (r/match-by-path router (:uri request))]
|
||||
|
|
@ -86,10 +96,7 @@
|
|||
path-params (:path-params match)
|
||||
endpoint (-> match :result method)
|
||||
interceptors (or (:queue endpoint) (:interceptors endpoint))
|
||||
request (-> request
|
||||
(impl/fast-assoc :path-params path-params)
|
||||
(impl/fast-assoc ::r/match match)
|
||||
(impl/fast-assoc ::r/router router))
|
||||
request (enrich-request request path-params match router)
|
||||
context (assoc context :request request)
|
||||
queue (interceptor/queue executor (concat default-interceptors interceptors))]
|
||||
(interceptor/enqueue executor context queue))
|
||||
|
|
@ -104,12 +111,15 @@
|
|||
and options map, with the following keys:
|
||||
|
||||
| key | description |
|
||||
| ----------------|-------------|
|
||||
| ------------------|-------------|
|
||||
| `:executor` | `reitit.interceptor.Executor` for the interceptor chain
|
||||
| `:interceptors` | Optional sequence of interceptors that are always run before any other interceptors, even for the default handler"
|
||||
| `:interceptors` | Optional sequence of interceptors that are always run before any other interceptors, even for the default handler
|
||||
| `:inject-match?` | Boolean to inject `match` into request under `:reitit.core/match` key (default true)
|
||||
| `:inject-router?` | Boolean to inject `router` into request under `:reitit.core/router` key (default true)"
|
||||
([router opts]
|
||||
(ring-handler router nil opts))
|
||||
([router default-handler {:keys [executor interceptors]}]
|
||||
([router default-handler {:keys [executor interceptors inject-match? inject-router?]
|
||||
:or {inject-match? true, inject-router? true}}]
|
||||
(let [default-handler (or default-handler (fn ([_]) ([_ respond _] (respond nil))))
|
||||
default-queue (->> [default-handler]
|
||||
(concat interceptors)
|
||||
|
|
@ -120,7 +130,9 @@
|
|||
(dissoc :data) ; data is already merged into routes
|
||||
(cond-> (seq 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)
|
||||
enrich-request (ring/create-enrich-request inject-match? inject-router?)
|
||||
enrich-default-request (ring/create-enrich-default-request inject-router?)]
|
||||
(with-meta
|
||||
(fn
|
||||
([request]
|
||||
|
|
@ -129,13 +141,10 @@
|
|||
path-params (:path-params match)
|
||||
endpoint (-> match :result method)
|
||||
interceptors (or (:queue endpoint) (:interceptors endpoint))
|
||||
request (-> request
|
||||
(impl/fast-assoc :path-params path-params)
|
||||
(impl/fast-assoc ::r/match match)
|
||||
(impl/fast-assoc ::r/router router))]
|
||||
request (enrich-request request path-params match router)]
|
||||
(or (interceptor/execute executor interceptors request)
|
||||
(interceptor/execute executor default-queue request)))
|
||||
(interceptor/execute executor default-queue (impl/fast-assoc request ::r/router router))))
|
||||
(interceptor/execute executor default-queue (enrich-default-request request))))
|
||||
([request respond raise]
|
||||
(let [default #(interceptor/execute executor default-queue % respond raise)]
|
||||
(if-let [match (r/match-by-path router (:uri request))]
|
||||
|
|
@ -143,10 +152,7 @@
|
|||
path-params (:path-params match)
|
||||
endpoint (-> match :result method)
|
||||
interceptors (or (:queue endpoint) (:interceptors endpoint))
|
||||
request (-> request
|
||||
(impl/fast-assoc :path-params path-params)
|
||||
(impl/fast-assoc ::r/match match)
|
||||
(impl/fast-assoc ::r/router router))
|
||||
request (enrich-request request path-params match router)
|
||||
respond' (fn [response]
|
||||
(if response
|
||||
(respond response)
|
||||
|
|
@ -154,7 +160,7 @@
|
|||
(if interceptors
|
||||
(interceptor/execute executor interceptors request respond' raise)
|
||||
(default request)))
|
||||
(default (impl/fast-assoc request ::r/router router))))
|
||||
(default (enrich-default-request request))))
|
||||
nil))
|
||||
{::r/router router}))))
|
||||
|
||||
|
|
|
|||
|
|
@ -226,20 +226,54 @@
|
|||
(not-found-handler request)))))]
|
||||
(create handler)))))
|
||||
|
||||
(defn create-enrich-request [inject-match? inject-router?]
|
||||
(cond
|
||||
(and inject-match? inject-router?)
|
||||
(fn enrich-request [request path-params match router]
|
||||
(-> request
|
||||
(impl/fast-assoc :path-params path-params)
|
||||
(impl/fast-assoc ::r/match match)
|
||||
(impl/fast-assoc ::r/router router)))
|
||||
inject-router?
|
||||
(fn enrich-request [request path-params _ router]
|
||||
(-> request
|
||||
(impl/fast-assoc :path-params path-params)
|
||||
(impl/fast-assoc ::r/router router)))
|
||||
inject-match?
|
||||
(fn enrich-request [request path-params match _]
|
||||
(-> request
|
||||
(impl/fast-assoc :path-params path-params)
|
||||
(impl/fast-assoc ::r/match match)))
|
||||
:else
|
||||
(fn enrich-request [request path-params _ _]
|
||||
(-> request
|
||||
(impl/fast-assoc :path-params path-params)))))
|
||||
|
||||
(defn create-enrich-default-request [inject-router?]
|
||||
(if inject-router?
|
||||
(fn enrich-request [request router]
|
||||
(impl/fast-assoc request ::r/router router))
|
||||
identity))
|
||||
|
||||
(defn ring-handler
|
||||
"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 wrap the ring-handler"
|
||||
| ------------------|-------------|
|
||||
| `:middleware` | Optional sequence of middleware that wrap the ring-handler
|
||||
| `:inject-match?` | Boolean to inject `match` into request under `:reitit.core/match` key (default true)
|
||||
| `:inject-router?` | Boolean to inject `router` into request under `:reitit.core/router` key (default true)"
|
||||
([router]
|
||||
(ring-handler router nil))
|
||||
([router default-handler]
|
||||
(ring-handler router default-handler nil))
|
||||
([router default-handler {:keys [middleware]}]
|
||||
([router default-handler {:keys [middleware inject-match? inject-router?]
|
||||
:or {inject-match? true, inject-router? true}}]
|
||||
(let [default-handler (or default-handler (fn ([_]) ([_ respond _] (respond nil))))
|
||||
wrap (if middleware (partial middleware/chain middleware) identity)]
|
||||
wrap (if middleware (partial middleware/chain middleware) identity)
|
||||
enrich-request (create-enrich-request inject-match? inject-router?)
|
||||
enrich-default-request (create-enrich-default-request inject-router?)]
|
||||
(with-meta
|
||||
(wrap
|
||||
(fn
|
||||
|
|
@ -249,24 +283,18 @@
|
|||
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))]
|
||||
request (enrich-request request path-params match router)]
|
||||
(or (handler request) (default-handler request)))
|
||||
(default-handler (impl/fast-assoc request ::r/router router))))
|
||||
(default-handler (enrich-default-request 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))]
|
||||
request (enrich-request request path-params match router)]
|
||||
((routes handler default-handler) request respond raise))
|
||||
(default-handler (impl/fast-assoc request ::r/router router) respond raise))
|
||||
(default-handler (enrich-default-request request) respond raise))
|
||||
nil)))
|
||||
{::r/router router}))))
|
||||
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
[reitit.impl :as impl]
|
||||
[reitit.ring :as ring]
|
||||
[reitit.core :as r])
|
||||
(:import (reitit Trie)))
|
||||
(:import (reitit Trie Trie$Matcher)))
|
||||
|
||||
;;
|
||||
;; start repl with `lein perf repl`
|
||||
|
|
@ -77,12 +77,12 @@
|
|||
[["/user/:id/profile/:type/" {:get (fn [{{:keys [id type]} :path-params}] (h11 id type))
|
||||
:put (fn [{{:keys [id type]} :path-params}] (h12 id type))
|
||||
:handler (fn [_] (h1x))}]
|
||||
#_["/user/:id/permissions/" {:get (fn [{{:keys [id]} :path-params}] (h21 id))
|
||||
["/user/:id/permissions/" {:get (fn [{{:keys [id]} :path-params}] (h21 id))
|
||||
:put (fn [{{:keys [id]} :path-params}] (h22 id))
|
||||
:handler (fn [_] (h2x))}]
|
||||
#_["/company/:cid/dept/:did/" {:put (fn [{{:keys [cid did]} :path-params}] (h30 cid did))
|
||||
["/company/:cid/dept/:did/" {:put (fn [{{:keys [cid did]} :path-params}] (h30 cid did))
|
||||
:handler (fn [_] (h3x))}]
|
||||
#_["/this/is/a/static/route" {:put (fn [_] (h40))
|
||||
["/this/is/a/static/route" {:put (fn [_] (h40))
|
||||
:handler (fn [_] (h4x))}]])
|
||||
(fn [_] (hxx))))
|
||||
|
||||
|
|
@ -94,18 +94,116 @@
|
|||
|
||||
(let [request {:request-method :get
|
||||
:uri "/user/1234/profile/compact/"}]
|
||||
(handler-reitit request)
|
||||
;; OLD: 1338ns
|
||||
;; NEW: 981ns
|
||||
;; JAVA: 805ns
|
||||
;; NO-INJECT: 704ns
|
||||
#_(cc/quick-bench
|
||||
(handler-reitit request)))
|
||||
(handler-reitit request))
|
||||
(handler-reitit request))
|
||||
|
||||
(comment
|
||||
(impl/segments "/user/1234/profile/compact")
|
||||
;; 145ns
|
||||
(cc/quick-bench
|
||||
(impl/segments "/user/1234/profile/compact")))
|
||||
|
||||
(comment
|
||||
(Trie/split "/user/1234/profile/compact")
|
||||
;; 91ns
|
||||
(cc/quick-bench
|
||||
(Trie/split "/user/1234/profile/compact")))
|
||||
|
||||
(comment
|
||||
(let [router (r/router ["/user/:id/profile/:type"])]
|
||||
(cc/quick-bench
|
||||
(r/match-by-path router "/user/1234/profile/compact"))))
|
||||
|
||||
(let [lookup ^Trie$Matcher (Trie/sample)]
|
||||
(Trie/lookup lookup "/user/1234/profile/compact")
|
||||
#_(cc/quick-bench
|
||||
(Trie/lookup lookup "/user/1234/profile/compact")))
|
||||
|
||||
(let [router (r/router [["/user/:id" ::1]
|
||||
["/user/:id/permissions" ::2]
|
||||
["/company/:cid/dept/:did" ::3]
|
||||
["/this/is/a/static/route" ::4]])]
|
||||
#_(cc/quick-bench
|
||||
(r/match-by-path router "/user/1234/profile/compact"))
|
||||
(r/match-by-path router "/user/1234"))
|
||||
|
||||
;; 281ns
|
||||
(let [router (r/router [["/user/:id/profile/:type" ::1]
|
||||
["/user/:id/permissions" ::2]
|
||||
["/company/:cid/dept/:did" ::3]
|
||||
["/this/is/a/static/route" ::4]])]
|
||||
#_(cc/quick-bench
|
||||
(r/match-by-path router "/user/1234/profile/compact"))
|
||||
(r/match-by-path router "/user/1234/profile/compact"))
|
||||
|
||||
(read-string
|
||||
(str
|
||||
(.matcher
|
||||
(doto (Trie.)
|
||||
(.add "/user" 1)
|
||||
#_(.add "/user/id/permissions" 2)
|
||||
(.add "/user/id/permissions2" 3)))))
|
||||
|
||||
(Trie/lookup
|
||||
(.matcher
|
||||
(doto (Trie.)
|
||||
(.add "/user/1" 1)
|
||||
(.add "/user/1/permissions" 2)))
|
||||
"/user/1")
|
||||
|
||||
(.matcher
|
||||
(doto (Trie.)
|
||||
(.add "/user/1" 1)
|
||||
(.add "/user/1/permissions" 2)))
|
||||
|
||||
;; 137ns
|
||||
(let [m (.matcher
|
||||
(doto (Trie.)
|
||||
(.add "/user/:id/profile/:type" 1)))]
|
||||
#_(cc/quick-bench
|
||||
(Trie/lookup m "/user/1234/profile/compact"))
|
||||
(Trie/lookup m "/user/1234/profile/compact"))
|
||||
|
||||
(comment
|
||||
|
||||
(let [matcher ^Trie$Matcher (Trie/sample)]
|
||||
(Trie/lookup matcher "/user/1234/profile/compact")
|
||||
(cc/quick-bench
|
||||
(Trie/lookup matcher "/user/1234/profile/compact")))
|
||||
|
||||
;; 173ns
|
||||
(let [lookup ^Trie$Matcher (Trie/tree2)]
|
||||
(Trie/lookup lookup "/user/1234/profile/compact")
|
||||
(cc/quick-bench
|
||||
(Trie/lookup lookup "/user/1234/profile/compact")))
|
||||
|
||||
|
||||
;; 140ns
|
||||
(let [lookup ^Trie$Matcher (Trie/tree1)]
|
||||
(Trie/lookup lookup "/user/1234/profile/compact")
|
||||
(cc/quick-bench
|
||||
(Trie/lookup lookup "/user/1234/profile/compact")))
|
||||
|
||||
;; 849ns (clojure, original)
|
||||
;; 599ns (java, initial)
|
||||
;; 810ns (linear)
|
||||
;; 173ns (fast split)
|
||||
(let [router (r/router ["/user/:id/profile/:type"])]
|
||||
(r/match-by-path router "/user/1234/profile/compact")
|
||||
(cc/quick-bench
|
||||
(r/match-by-path router "/user/1234/profile/compact")))
|
||||
|
||||
;; 849ns (clojure, original)
|
||||
;; 599ns (java, initial)
|
||||
;; 173ns (java, optimized)
|
||||
(let [router (r/router [["/user/:id/profile/:type/" ::1]
|
||||
["/user/:id/permissions/" ::2]
|
||||
["/company/:cid/dept/:did/" ::3]
|
||||
["/this/is/a/static/route" ::4]])]
|
||||
(cc/quick-bench
|
||||
(r/match-by-path router "/user/1234/profile/compact")))
|
||||
|
||||
|
|
@ -129,10 +227,16 @@
|
|||
|
||||
(import '[reitit Util])
|
||||
|
||||
#_(cc/quick-bench
|
||||
(Trie/split "/this/is/a/static/route"))
|
||||
|
||||
(comment
|
||||
(Util/matchURI "/user/1234/profile/compact/" ["/user/" :id "/profile/" :type "/"])
|
||||
(cc/quick-bench
|
||||
(Util/matchURI "/user/1234/profile/compact/" ["/user/" :id "/profile/" :type "/"]))
|
||||
|
||||
(cc/quick-bench
|
||||
(Trie/split "/user/1234/profile/compact/"))
|
||||
|
||||
(cc/quick-bench
|
||||
(.split "/user/1234/profile/compact/" "/" 666)))
|
||||
|
||||
(import '[reitit Segment2])
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue