blob: 49360649544d4c66f5c27a498e91753aa6492fb5 (
about) (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
|
(ns reverse-routing.core
(:require [clojure.string :as string]))
(defn wrap-reverse-routing [handler & {:keys [root] :or {:root ""}}]
(fn [request]
(let [route-table (->> handler meta ::routes)
request (assoc request
::reverse-routes route-table
::root root)]
(handler request))))
(defn ^:private routing [request & handlers]
(some #(% request) handlers))
(defn routes [& handlers]
(let [merge-first (partial merge-with (fn [x y] x))]
(apply vary-meta #(apply routing % handlers)
update-in [::routes]
merge-first (map (comp ::routes meta) handlers))))
(defmacro context [path args & routes]
(let [string-path (if (vector? path) (first path) path)]
`(with-meta (compojure.core/context ~path ~args ~@routes)
{::routes (let [path-keys# (:keys (clout.core/route-compile ~string-path))
~args [] ;; wow. could this be hackier? I doubt it.
]
(->> (for [routes# (map (comp ::routes meta) (list ~@routes))
[key# val#] routes#]
[key# {:uri (str ~string-path (:uri val#))
:args (concat path-keys# (:args val#))
:type (:type val#)}])
(into {})))})))
(defmacro register-route [route-name [type path args & body :as route]]
(let [string-path (if (vector? path) (first path) path)]
`(with-meta ~route
{::routes {~route-name {:uri ~string-path
:type ~(keyword (string/lower-case (name type)))
:args (:keys (clout.core/route-compile ~string-path))}}})))
(defn url-for [request route & arg-values]
(let [{:keys [uri type args]} (-> request ::reverse-routes route)
root-path (::root request)]
(str root-path
(reduce (fn [string [name val]]
(clojure.string/replace string (str name) (str val)))
uri (map vector args arg-values)))))
(comment
(require '[compojure.core :refer [GET]])
(def test-routes
(-> (routes
(->> (GET "/user/:id" {{id :id} :params :as request}
(url-for request :get-something id))
(register-route :get-user))
(->> (GET "/person/:id" {{id :id} :params :as request}
(url-for request :get-user id))
(register-route :get-person))
(context "/something/:id" [id]
(GET "/nom" []
"something, blah!")
(->> (GET "/name" {:as request}
(url-for request :get-person id))
(register-route :get-something))
(->> (GET ["/nam/:blah", :blah #"1\d+"] {{bloo :blah} :params :as request}
(url-for request :get-something-else id 10))
(register-route :get-something-else))))
wrap-reverse-routing))
(test-routes {:request-method :get
:scheme :http
;;:uri "/something/15/name"
;;:uri "/person/15"
:uri "/user/15"
;;:uri "/something/15/nam/12"
;;:uri "/something/10/nom"
:remote-addr "127.0.0.1"
:server-port 8080
:server-name "something"})
)
|