-
Notifications
You must be signed in to change notification settings - Fork 149
Creating your own metadata handlers
Juho Teperi edited this page Dec 18, 2015
·
2 revisions
Compojure-api handles the route metadata by calling the multimethod compojure.api.meta/restructure-param
with
metadata key as a dispatch value.
Multimethods take three parameters:
- metadata key
- metadata value
- accumulator map with keys
-
:lets
, a vector of let bindings applied first before the actual body -
:letks
, a vector of letk bindings applied second before the actual body -
:middlewares
, a vector of route specific middlewares (applied from left to right) -
:parameters
, meta-data of a route (without the key & value for the current multimethod) -
:body
, a sequence of the actual route body
-
.. and should return the modified accumulator. Multimethod calls are reduced to produce the final accumulator for
code generation. Defined key-value -based metadatas for routes are guaranteed to run on top-to-bottom order of the so
all the potential let
and letk
variable overrides can be solved by the client. Default implementation is to keep
the key & value as a route metadata.
You can add your own metadata-handlers by implementing the multimethod:
(defmethod compojure.api.meta/restructure-param :auth
[_ token {:keys [parameters lets body middlewares] :as acc}]
"Make sure the request has X-AccessToken header and that it's value is 123. Binds the value into a variable"
(-> acc
(update-in [:lets] into [{{token "x-accesstoken"} :headers} '+compojure-api-request+])
(assoc :body `((if (= ~token "123")
(do ~@body)
(ring.util.http-response/forbidden "Auth required"))))))
Using it:
(GET* "/current-session" []
:auth token
(ok {:token token}))
macroexpanding-1 it too see what's get generated:
(clojure.pprint/pprint
(macroexpand-1 `(GET* "/current-session" []
:auth token
(ok {:token token}))))
(compojure.core/GET "/current-session" [:as +compojure-api-request+]
(clojure.core/let [{{examples.thingie/token "x-accesstoken"} :headers} +compojure-api-request+]
(do
(if
(clojure.core/= examples.thingie/token "123")
(do (ring.util.http-response/ok {:token examples.thingie/token}))
(ring.util.http-response/forbidden "Auth required")))))