mirror of
https://github.com/metosin/reitit.git
synced 2025-12-20 17:41:11 +00:00
http-router
This commit is contained in:
parent
20fa00beaa
commit
044c0d6163
3 changed files with 127 additions and 91 deletions
|
|
@ -335,7 +335,7 @@
|
||||||
(str ":single-static-path-router requires exactly 1 static route: " compiled-routes)
|
(str ":single-static-path-router requires exactly 1 static route: " compiled-routes)
|
||||||
{:routes compiled-routes})))
|
{:routes compiled-routes})))
|
||||||
(let [[n :as names] (find-names compiled-routes opts)
|
(let [[n :as names] (find-names compiled-routes opts)
|
||||||
[[p data result] :as compiled] compiled-routes
|
[[p data result]] compiled-routes
|
||||||
p #?(:clj (.intern ^String p) :cljs p)
|
p #?(:clj (.intern ^String p) :cljs p)
|
||||||
match (->Match p data result {} p)
|
match (->Match p data result {} p)
|
||||||
routes (uncompile-routes compiled-routes)]
|
routes (uncompile-routes compiled-routes)]
|
||||||
|
|
|
||||||
|
|
@ -5,37 +5,16 @@
|
||||||
[reitit.core :as r]
|
[reitit.core :as r]
|
||||||
[reitit.impl :as impl]))
|
[reitit.impl :as impl]))
|
||||||
|
|
||||||
(defrecord Endpoint [data handler path method interceptors])
|
(defrecord Endpoint [data handler path method interceptors queue])
|
||||||
|
|
||||||
(defn http-handler
|
(defprotocol Executor
|
||||||
"Creates a ring-handler out of a http-router and
|
(queue
|
||||||
an interceptor runner.
|
[this interceptors]
|
||||||
Optionally takes a ring-handler which is called
|
"takes a sequence of interceptors and compiles them to queue for the executor")
|
||||||
in no route matches."
|
(execute
|
||||||
([router runner]
|
[this request interceptors]
|
||||||
(http-handler router runner nil))
|
[this request interceptors respond raise]
|
||||||
([router runner default-handler]
|
"executes the interceptor chain"))
|
||||||
(let [default-handler (or default-handler (fn ([_]) ([_ respond _] (respond nil))))]
|
|
||||||
(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)
|
|
||||||
interceptors (-> result method :interceptors)
|
|
||||||
request (-> request
|
|
||||||
(impl/fast-assoc :path-params path-params)
|
|
||||||
(impl/fast-assoc ::r/match match)
|
|
||||||
(impl/fast-assoc ::r/router router))]
|
|
||||||
(:response (runner interceptors request)))
|
|
||||||
(default-handler request)))
|
|
||||||
{::r/router router}))))
|
|
||||||
|
|
||||||
(defn get-router [handler]
|
|
||||||
(-> handler meta ::r/router))
|
|
||||||
|
|
||||||
(defn get-match [request]
|
|
||||||
(::r/match request))
|
|
||||||
|
|
||||||
(defn coerce-handler [[path data] {:keys [expand] :as opts}]
|
(defn coerce-handler [[path data] {:keys [expand] :as opts}]
|
||||||
[path (reduce
|
[path (reduce
|
||||||
|
|
@ -44,7 +23,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] opts]
|
(defn compile-result [[path data] {:keys [::queue] :as opts}]
|
||||||
(let [[top childs] (ring/group-keys data)
|
(let [[top childs] (ring/group-keys data)
|
||||||
->handler (fn [handler]
|
->handler (fn [handler]
|
||||||
(if handler
|
(if handler
|
||||||
|
|
@ -54,10 +33,13 @@
|
||||||
(let [data (update data :handler ->handler)]
|
(let [data (update data :handler ->handler)]
|
||||||
(interceptor/compile-result [path data] opts scope)))
|
(interceptor/compile-result [path data] opts scope)))
|
||||||
->endpoint (fn [p d m s]
|
->endpoint (fn [p d m s]
|
||||||
(-> (compile [p d] opts s)
|
(let [compiled (compile [p d] opts s)
|
||||||
|
interceptors (:interceptors compiled)]
|
||||||
|
(-> compiled
|
||||||
(map->Endpoint)
|
(map->Endpoint)
|
||||||
(assoc :path p)
|
(assoc :path p)
|
||||||
(assoc :method m)))
|
(assoc :method m)
|
||||||
|
(assoc :queue ((or queue identity) interceptors)))))
|
||||||
->methods (fn [any? data]
|
->methods (fn [any? data]
|
||||||
(reduce
|
(reduce
|
||||||
(fn [acc method]
|
(fn [acc method]
|
||||||
|
|
@ -94,3 +76,53 @@
|
||||||
([data opts]
|
([data opts]
|
||||||
(let [opts (meta-merge {:coerce coerce-handler, :compile compile-result} opts)]
|
(let [opts (meta-merge {:coerce coerce-handler, :compile compile-result} opts)]
|
||||||
(r/router data opts))))
|
(r/router data opts))))
|
||||||
|
|
||||||
|
(defn ring-handler
|
||||||
|
"Creates a ring-handler out of a http-router,
|
||||||
|
a default ring-handler and options map, with the following keys:
|
||||||
|
|
||||||
|
| key | description |
|
||||||
|
| ----------------|-------------|
|
||||||
|
| `:executor` | [[Executor]] for the interceptor chain
|
||||||
|
| `:interceptors` | Optional sequence of interceptors that are always run before any other interceptors, even for the default handler"
|
||||||
|
[router default-handler {:keys [executor interceptors]}]
|
||||||
|
(let [default-handler (or default-handler (fn ([_]) ([_ respond _] (respond nil))))
|
||||||
|
default-queue (queue executor (interceptor/into-interceptor (concat interceptors [default-handler]) nil (r/options router)))
|
||||||
|
router-opts (-> (r/options router)
|
||||||
|
(assoc ::queue (partial queue executor))
|
||||||
|
(update :interceptors (partial concat interceptors)))
|
||||||
|
router (router (r/routes router) router-opts)]
|
||||||
|
(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)
|
||||||
|
interceptors (-> result method :interceptors)
|
||||||
|
request (-> request
|
||||||
|
(impl/fast-assoc :path-params path-params)
|
||||||
|
(impl/fast-assoc ::r/match match)
|
||||||
|
(impl/fast-assoc ::r/router router))]
|
||||||
|
(execute executor interceptors request))
|
||||||
|
(execute executor default-queue 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)
|
||||||
|
interceptors (-> result method :interceptors)
|
||||||
|
request (-> request
|
||||||
|
(impl/fast-assoc :path-params path-params)
|
||||||
|
(impl/fast-assoc ::r/match match)
|
||||||
|
(impl/fast-assoc ::r/router router))]
|
||||||
|
(execute executor interceptors request respond raise))
|
||||||
|
(execute executor default-queue request respond raise))
|
||||||
|
nil))
|
||||||
|
{::r/router router})))
|
||||||
|
|
||||||
|
(defn get-router [handler]
|
||||||
|
(-> handler meta ::r/router))
|
||||||
|
|
||||||
|
(defn get-match [request]
|
||||||
|
(::r/match request))
|
||||||
|
|
|
||||||
|
|
@ -3,8 +3,7 @@
|
||||||
[reitit.middleware :as middleware]
|
[reitit.middleware :as middleware]
|
||||||
[reitit.core :as r]
|
[reitit.core :as r]
|
||||||
[reitit.impl :as impl]
|
[reitit.impl :as impl]
|
||||||
#?@(:clj [
|
#?@(:clj [[ring.util.mime-type :as mime-type]
|
||||||
[ring.util.mime-type :as mime-type]
|
|
||||||
[ring.util.response :as response]])
|
[ring.util.response :as response]])
|
||||||
[clojure.string :as str]))
|
[clojure.string :as str]))
|
||||||
|
|
||||||
|
|
@ -19,6 +18,61 @@
|
||||||
[top (assoc childs k v)]
|
[top (assoc childs k v)]
|
||||||
[(assoc top k v) childs])) [{} {}] data))
|
[(assoc top k v) childs])) [{} {}] data))
|
||||||
|
|
||||||
|
(defn coerce-handler [[path data] {:keys [expand] :as opts}]
|
||||||
|
[path (reduce
|
||||||
|
(fn [acc method]
|
||||||
|
(if (contains? acc method)
|
||||||
|
(update acc method expand opts)
|
||||||
|
acc)) data http-methods)])
|
||||||
|
|
||||||
|
(defn compile-result [[path data] opts]
|
||||||
|
(let [[top childs] (group-keys data)
|
||||||
|
->endpoint (fn [p d m s]
|
||||||
|
(-> (middleware/compile-result [p d] opts s)
|
||||||
|
(map->Endpoint)
|
||||||
|
(assoc :path p)
|
||||||
|
(assoc :method m)))
|
||||||
|
->methods (fn [any? data]
|
||||||
|
(reduce
|
||||||
|
(fn [acc method]
|
||||||
|
(cond-> acc
|
||||||
|
any? (assoc method (->endpoint path data method nil))))
|
||||||
|
(map->Methods {})
|
||||||
|
http-methods))]
|
||||||
|
(if-not (seq childs)
|
||||||
|
(->methods true top)
|
||||||
|
(reduce-kv
|
||||||
|
(fn [acc method data]
|
||||||
|
(let [data (meta-merge top data)]
|
||||||
|
(assoc acc method (->endpoint path data method method))))
|
||||||
|
(->methods (:handler top) data)
|
||||||
|
childs))))
|
||||||
|
|
||||||
|
;;
|
||||||
|
;; public api
|
||||||
|
;;
|
||||||
|
|
||||||
|
(defn router
|
||||||
|
"Creates a [[reitit.core/Router]] from raw route data and optionally an options map with
|
||||||
|
support for http-methods and Middleware. See [docs](https://metosin.github.io/reitit/)
|
||||||
|
for details.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
(router
|
||||||
|
[\"/api\" {:middleware [wrap-format wrap-oauth2]}
|
||||||
|
[\"/users\" {:get get-user
|
||||||
|
:post update-user
|
||||||
|
:delete {:middleware [wrap-delete]
|
||||||
|
:handler delete-user}}]])
|
||||||
|
|
||||||
|
See router options from [[reitit.core/router]] and [[reitit.middleware/router]]."
|
||||||
|
([data]
|
||||||
|
(router data nil))
|
||||||
|
([data opts]
|
||||||
|
(let [opts (meta-merge {:coerce coerce-handler, :compile compile-result} opts)]
|
||||||
|
(r/router data opts))))
|
||||||
|
|
||||||
(defn routes
|
(defn routes
|
||||||
"Create a ring handler by combining several handlers into one."
|
"Create a ring handler by combining several handlers into one."
|
||||||
[& handlers]
|
[& handlers]
|
||||||
|
|
@ -156,7 +210,8 @@
|
||||||
(impl/fast-assoc ::r/match match)
|
(impl/fast-assoc ::r/match match)
|
||||||
(impl/fast-assoc ::r/router router))]
|
(impl/fast-assoc ::r/router router))]
|
||||||
((routes handler default-handler) request respond raise))
|
((routes handler default-handler) request respond raise))
|
||||||
(default-handler request respond raise))))
|
(default-handler request respond raise))
|
||||||
|
nil))
|
||||||
{::r/router router}))))
|
{::r/router router}))))
|
||||||
|
|
||||||
(defn get-router [handler]
|
(defn get-router [handler]
|
||||||
|
|
@ -164,54 +219,3 @@
|
||||||
|
|
||||||
(defn get-match [request]
|
(defn get-match [request]
|
||||||
(::r/match request))
|
(::r/match request))
|
||||||
|
|
||||||
(defn coerce-handler [[path data] {:keys [expand] :as opts}]
|
|
||||||
[path (reduce
|
|
||||||
(fn [acc method]
|
|
||||||
(if (contains? acc method)
|
|
||||||
(update acc method expand opts)
|
|
||||||
acc)) data http-methods)])
|
|
||||||
|
|
||||||
(defn compile-result [[path data] opts]
|
|
||||||
(let [[top childs] (group-keys data)
|
|
||||||
->endpoint (fn [p d m s]
|
|
||||||
(-> (middleware/compile-result [p d] opts s)
|
|
||||||
(map->Endpoint)
|
|
||||||
(assoc :path p)
|
|
||||||
(assoc :method m)))
|
|
||||||
->methods (fn [any? data]
|
|
||||||
(reduce
|
|
||||||
(fn [acc method]
|
|
||||||
(cond-> acc
|
|
||||||
any? (assoc method (->endpoint path data method nil))))
|
|
||||||
(map->Methods {})
|
|
||||||
http-methods))]
|
|
||||||
(if-not (seq childs)
|
|
||||||
(->methods true top)
|
|
||||||
(reduce-kv
|
|
||||||
(fn [acc method data]
|
|
||||||
(let [data (meta-merge top data)]
|
|
||||||
(assoc acc method (->endpoint path data method method))))
|
|
||||||
(->methods (:handler top) data)
|
|
||||||
childs))))
|
|
||||||
|
|
||||||
(defn router
|
|
||||||
"Creates a [[reitit.core/Router]] from raw route data and optionally an options map with
|
|
||||||
support for http-methods and Middleware. See [docs](https://metosin.github.io/reitit/)
|
|
||||||
for details.
|
|
||||||
|
|
||||||
Example:
|
|
||||||
|
|
||||||
(router
|
|
||||||
[\"/api\" {:middleware [wrap-format wrap-oauth2]}
|
|
||||||
[\"/users\" {:get get-user
|
|
||||||
:post update-user
|
|
||||||
:delete {:middleware [wrap-delete]
|
|
||||||
:handler delete-user}}]])
|
|
||||||
|
|
||||||
See router options from [[reitit.core/router]] and [[reitit.middleware/router]]."
|
|
||||||
([data]
|
|
||||||
(router data nil))
|
|
||||||
([data opts]
|
|
||||||
(let [opts (meta-merge {:coerce coerce-handler, :compile compile-result} opts)]
|
|
||||||
(r/router data opts))))
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue