comments
This commit is contained in:
parent
bd038047db
commit
a5010e423e
|
@ -12,6 +12,12 @@
|
||||||
(~fail-response ~request))))
|
(~fail-response ~request))))
|
||||||
|
|
||||||
(defmacro checked-routes
|
(defmacro checked-routes
|
||||||
|
"Wraps any number of routes with one or more filters which are run before any of the
|
||||||
|
wrapped routes are executed. If any of the filters return nil, fail-response is
|
||||||
|
returned by the server instead of the running a route handler. Filter functions
|
||||||
|
should accept a Ring request as the first argument and return a Ring request map
|
||||||
|
if the filter logic passed. The same Ring request map is threaded through all of
|
||||||
|
the filters before eventually being passed on to the route handler."
|
||||||
[checks fail-response & routes]
|
[checks fail-response & routes]
|
||||||
`(fn [request#]
|
`(fn [request#]
|
||||||
(let [result# (threaded-checks request# ~checks ~fail-response)]
|
(let [result# (threaded-checks request# ~checks ~fail-response)]
|
||||||
|
@ -24,8 +30,17 @@
|
||||||
(response/status 500)))
|
(response/status 500)))
|
||||||
|
|
||||||
(defmacro checked-route
|
(defmacro checked-route
|
||||||
|
"Used in place of a normal Compojure route handler's body. Applies a series of
|
||||||
|
filters to the route/request parameters before finally running the handler
|
||||||
|
body itself. All of the filters used should accept a Ring request as the first
|
||||||
|
argument and return a filtered Ring request, or nil if the filter failed. Use
|
||||||
|
routefn at the end to wrap your actual route handler logic. The arguments it
|
||||||
|
receives are destructured the same as with a normal Compojure route, but the
|
||||||
|
request's :safe-params map is used instead of :params to find the values to
|
||||||
|
bind to the arguments listed. If any of the filters fail, the :on-fail response
|
||||||
|
is returned (or a default HTTP 500 response if not specified)."
|
||||||
{:arglists '([& body]
|
{:arglists '([& body]
|
||||||
[:on-fail fail-response & body])}
|
[:on-fail fail-response & body])}
|
||||||
[& body]
|
[& body]
|
||||||
(let [has-fail-response? (= :on-fail (first body))
|
(let [has-fail-response? (= :on-fail (first body))
|
||||||
fail-response (if has-fail-response? (second body) default-check-error-response)
|
fail-response (if has-fail-response? (second body) default-check-error-response)
|
||||||
|
@ -34,27 +49,46 @@
|
||||||
(threaded-checks request# ~body ~fail-response))))
|
(threaded-checks request# ~body ~fail-response))))
|
||||||
|
|
||||||
(defmacro checked
|
(defmacro checked
|
||||||
|
"Convenience method of defining a 'checked' Compojure route. Place this at the
|
||||||
|
start of the Compojure route definition (before GET, PUT, etc) and omit the
|
||||||
|
params vector after the route path. The route handler body is automatically
|
||||||
|
wrapped in a call to checked-route, so you just define the contents of
|
||||||
|
it as you would if you were using checked-route manually."
|
||||||
{:arglists '([method-fn path & body]
|
{:arglists '([method-fn path & body]
|
||||||
[method-fn path :on-fail fail-response & body])}
|
[method-fn path :on-fail fail-response & body])}
|
||||||
[method-fn path & body]
|
[method-fn path & body]
|
||||||
`(~method-fn ~path []
|
`(~method-fn ~path []
|
||||||
(checked-route ~@body)))
|
(checked-route ~@body)))
|
||||||
|
|
||||||
(defmacro routefn [request args & body]
|
(defmacro routefn
|
||||||
|
"The final form present in a checked-route call. The forms in body are executed
|
||||||
|
only if none of the previous filters failed. The arguments vector is destructured
|
||||||
|
the same was as normal Compojure route parameter destructuring is done, except
|
||||||
|
that parameters come from the request's :safe-params map instead."
|
||||||
|
[request args & body]
|
||||||
(if (vector? args)
|
(if (vector? args)
|
||||||
`(let [~@(destructure-route-bindings args :safe-params request)] ~@body)
|
`(let [~@(destructure-route-bindings args :safe-params request)] ~@body)
|
||||||
`(let [~args ~request] ~@body)))
|
`(let [~args ~request] ~@body)))
|
||||||
|
|
||||||
(defn safe
|
(defn safe
|
||||||
|
"Marks one or more parameters as safe (copying them from the request's :params
|
||||||
|
map to :safe-params)."
|
||||||
[request & params]
|
[request & params]
|
||||||
(let [safe-params (select-keys (:params request) params)]
|
(let [safe-params (select-keys (:params request) params)]
|
||||||
(update-in request [:safe-params] merge safe-params)))
|
(update-in request [:safe-params] merge safe-params)))
|
||||||
|
|
||||||
(defn validate
|
(defn validate
|
||||||
|
"Validates the specified parameter using function f which gets passed the value
|
||||||
|
of the parameter and any additional arguments given. If f returns a 'truthy' value
|
||||||
|
the parameter is marked safe."
|
||||||
[request param f & args]
|
[request param f & args]
|
||||||
(if (apply f (get-in request [:params param]) args)
|
(if (apply f (get-in request [:params param]) args)
|
||||||
(safe request param)))
|
(safe request param)))
|
||||||
|
|
||||||
(defn transform
|
(defn transform
|
||||||
[request param-k f & args]
|
"Transforms the specified parameter using function f which gets passed the value
|
||||||
(apply update-in request [:params param-k] f args))
|
of the parameter and any additional arguments given. Note that this does not
|
||||||
|
mark a parameter safe after transformation. This is intended to be used to
|
||||||
|
perform any pre-validation transformations if necessary."
|
||||||
|
[request param f & args]
|
||||||
|
(apply update-in request [:params param] f args))
|
||||||
|
|
Reference in a new issue