An example of how to make conditional interceptors that enqueue new interceptors
;; Let's start with a simple conditional interceptor that works with functions... | |
(defn conditional-context | |
"Given a keyword name and any variable predicate and terminator function pairs, | |
return an interceptor that will apply the terminator function paired to the first | |
truthy predicate. Predicates and terminators are both given the context as | |
the only argument. | |
If all predicates fail, the original context is returned." | |
[name-kw & pred-terms] | |
{:pre [(even? (count pred-terms))]} | |
(let [pred-term-pairs (partition 2 pred-terms)] | |
(interceptor/interceptor | |
:name name-kw | |
:enter (fn [context] | |
(or | |
(first | |
(keep (fn [[pred term]] (when (pred context) | |
(term context))) | |
pred-term-pairs)) | |
context))))) | |
;; Let's write a predicate function that inspects a specific header | |
(defn forwarded-from-foo? | |
[ctx] | |
(= (get-in ctx [:request :headers "X-Forwarded-From") "foo.com")) | |
;; We can now use Pedestal's interceptor chain API to enhance it... | |
(require '[io.pedestal.interceptor.chain :as chain]) | |
(defn handle-foo | |
"Given a context (map) | |
return a new context that has enqueued the additional interceptors | |
needed to handle Foo.com requests." | |
[ctx] | |
(chain/enqueue ctx | |
[ | |
;; ... any interceptors you want in here, including another router | |
])) | |
;; Putting it all together | |
(conditional-context ::my-cond-interceptor | |
forwarded-from-foo? handle-foo | |
:else #(assoc :response {:body "Nothing" :headers {} :status 200})) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment