blob: 3d373ebb04c00291fbd67c7f37d3a68c536dd3e2 (
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
83
84
85
86
87
88
89
90
91
92
93
94
|
(ns abra.core
(:require clout.core
compojure.core
[clojure.string :as string]))
(def ^:private ^:dynamic *lookup-route* nil)
(def ^:private ^:dynamic *root* nil)
(defn ^:private deref-if-var [arg]
(if (var? arg)
(deref arg)
arg))
(defn wrap-reverse-routing [handler & {:keys [root] :or {:root ""}}]
(fn [request]
(binding [*lookup-route* (->> handler deref-if-var meta ::lookup)
*root* root]
(handler request))))
(defn ^:private lookup-route [route & handlers]
(->> handlers
(map (comp ::lookup meta deref-if-var))
(some #(if % (% route)))))
(defn ^:private routing [request & handlers]
(some #(% request) handlers))
(defn routes [& handlers]
(vary-meta #(apply routing % handlers)
assoc ::lookup #(apply lookup-route % handlers)))
(defmacro let-routes [bindings & handlers]
`(let ~bindings (routes ~@handlers)))
(defmacro when-routes [cond & handlers]
`(if ~cond (routes ~@handlers) (routes)))
(defmacro defroutes [name & handlers]
`(def ~name (routes ~@handlers)))
(defmacro context [path args & routes]
(let [string-path (if (vector? path) (first path) path)
path-keys (vec (:keys (clout.core/route-compile string-path)))
keylen (count path-keys)
lookup-fn `(fn [[route-name# args#]]
(if (>= (count args#) ~keylen)
(let [~args args#
r# (try (#'lookup-route [route-name# (vec (drop ~keylen args#))]
~@routes)
(catch Exception _#))
{uri# :uri, args# :args} r#]
(if r#
(assoc r#
:uri (str ~string-path uri#)
:args (vec (concat ~path-keys args#)))))))]
`(vary-meta (compojure.core/context ~path ~args
(routes ~@routes))
assoc ::lookup ~lookup-fn)))
(defmacro register-route [route-name [type path args & body :as route]]
(let [string-path (if (vector? path) (first path) path)
route-args (:keys (clout.core/route-compile string-path))
routes-map {:uri string-path
:type (keyword (string/lower-case (name type)))
:args (vec route-args)}]
`(vary-meta ~route
assoc ::lookup (fn [[name# args#]]
(if (and (= name# ~route-name)
(= (count args#) (count ~(vec route-args))))
~routes-map)))))
(defn add-middleware [handler middleware & args]
(let [result (apply middleware handler args)]
(vary-meta result
assoc ::lookup (fn [[name args]]
(let [lookup-fn (-> (deref-if-var handler)
meta
::lookup)]
(lookup-fn [name args]))))))
(defmacro with-url-fn [f & body]
`(binding [*lookup-route* (fn [x#] (apply ~f x#))
*root* ""]
~@body))
(defn url-for [route & arg-values]
(let [spec (*lookup-route* [route arg-values])
{:keys [uri type args]} spec
root-path *root*]
(if spec
(str root-path
(reduce (fn [string [name val]]
(clojure.string/replace string (str name) (str val)))
uri (map vector args arg-values))))))
|