Ring handler a function which accepts a request (map) and returns a response (map).
Ring middleware
function (handler, &args -> function(request -> response) because it is a closure handler and &args are in scope within the returned handler function.
a function which accepts a "next handler" (the next handler in the chain) + any extra arguments and returns a handler (function), which will accept a request and return a response.
the returned function can fetch the response by calling the given handler with the given request.
- it could return a handler function which changes the request and then calls the given "next handler" with changed request.
- it could return a handler function which calls the given "next handler" and changes the given response before returning it.
- the handler returned by the middleware does not have to call the given "next handler", it can return a response, i.e. terminate the middleware chain.
so the returned handler function has access to the "next handler" which is only actually used to get the response, via (handler request)
..
;; middleware which does nothing
(defn wrap-nothing [handler]
(fn [request]
(handler request)))
;; middleware which terminates the chain
(defn wrap-nothing [handler]
(fn [request]
(response "Terminated"))
;; middleware which prints the request
(defn wrap-print-request [handler]
(fn [request]
(println request)
(handler request))
;; adds a uuid to the response
(defn wrap-uuid [handler]
(fn [request]
(let [response (handler request)
uuid (..)]
(assoc response :uuid uuid))))
;; adds a uuid to the request
(defn wrap-uuid [handler]
(fn [request]
(handler (assoc request :uuid uuid))))
(defn wrap-joke [handler joke]
(fn [request]
(let [response (handler request)]
(assoc response :joke joke))))
Chaing the middlewares
(def app
(-> handler
(wrap-uuid)
(wrap-joke "How did the chicken cross the road?")))
same as (wrap-joke (wrap-uuid handler) "How did the chicken cross the road?")
, so the first form is evaludated first and is wrapped
in the following forms, the last being the outermost form which wraps everything.
Typically the first handler passed to the threading macro will be a handler which does routing.
Note that app
will return a handler, so:
(app request) ;; => response
https://github.com/ring-clojure/ring/wiki/Middleware-Patterns
(defroutes (GET "/" [] home-page-handler)
defroutes
returns a handler (function)
Very clear! This solved my issue. Thank you.