-
Notifications
You must be signed in to change notification settings - Fork 250
/
pedestal.clj
74 lines (65 loc) · 2.15 KB
/
pedestal.clj
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
(ns reitit.pedestal
(:require [io.pedestal.interceptor.chain :as chain]
[io.pedestal.interceptor :as interceptor]
[io.pedestal.http :as http]
[reitit.interceptor]
[reitit.http])
(:import (reitit.interceptor Executor)
(java.lang.reflect Method)))
;; TODO: variadic
(defn- arities [f]
(->> (class f)
.getDeclaredMethods
(filter (fn [^Method m] (= "invoke" (.getName m))))
(map #(alength (.getParameterTypes ^Method %)))
(set)))
(defn- error-without-arity-2? [{error-fn :error}]
(and error-fn (not (contains? (arities error-fn) 2))))
(defn- error-arity-2->1 [error]
(fn [context ex]
(let [{ex :error :as context} (error (assoc context :error ex))]
(if ex
(-> context
(assoc ::chain/error ex)
(dissoc :error))
context))))
(defn- wrap-error-arity-2->1 [interceptor]
(update interceptor :error error-arity-2->1))
(defn ->interceptor [interceptor]
(cond
(interceptor/interceptor? interceptor)
interceptor
(->> (select-keys interceptor [:enter :leave :error]) (vals) (keep identity) (seq))
(interceptor/interceptor
(if (error-without-arity-2? interceptor)
(wrap-error-arity-2->1 interceptor)
interceptor))))
;;
;; Public API
;;
(def pedestal-executor
(reify
Executor
(queue [_ interceptors]
(->> interceptors
(map (fn [{::interceptor/keys [handler] :as interceptor}]
(or handler interceptor)))
(keep ->interceptor)))
(enqueue [_ context interceptors]
(chain/enqueue context interceptors))))
(defn routing-interceptor
([router]
(routing-interceptor router nil))
([router default-handler]
(routing-interceptor router default-handler nil))
([router default-handler {:keys [interceptors]}]
(interceptor/interceptor
(reitit.http/routing-interceptor
router
default-handler
{:executor pedestal-executor
:interceptors interceptors}))))
(defn replace-last-interceptor [service-map interceptor]
(-> service-map
(update ::http/interceptors pop)
(update ::http/interceptors conj interceptor)))