Es hilft zu visualisieren, was Middleware eigentlich ist.
(defn middleware [handler]
(fn [request]
;; ...
;; Do something to the request before sending it down the chain.
;; ...
(let [response (handler request)]
;; ...
;; Do something to the response that's coming back up the chain.
;; ...
response)))
Das war genau der a-ha-Moment für mich.
Was auf den ersten Blick verwirrend ist, ist, dass Middleware nicht auf die Anfrage angewendet wird, woran Sie denken.
Daran erinnern, dass ein Ring App ist nur eine Funktion, die eine Anforderung und gibt eine Antwort nimmt (was bedeutet, dass es einen Handler):
((fn [request] {:status 200, ...}) request) ;=> response
Lasst uns ein wenig verkleinern. Wir bekommen einen anderen Handler:
((GET "/" [] "Hello") request) ;=> response
Lassen Sie uns ein wenig mehr herauszoomen. Wir finden die my-routes
Handler:
(my-routes request) ;=> response
Nun, was ist, wenn Sie etwas vor dem Senden der Anforderung an den my-routes
Handler tun wollte? Sie können es mit einem anderen Handler einpacken.
((fn [req] (println "Request came in!") (my-routes req)) request) ;=> response
Das ist ein wenig schwer zu lesen, also lasst uns aus Gründen der Klarheit ausbrechen. Wir können eine Funktion definieren, die diesen Handler zurückgibt. Middleware sind Funktionen, die einen Handler nehmen und einen anderen Handler umschließen. Es gibt keine Antwort zurück. Es gibt einen Handler zurück, der eine Antwort zurückgeben kann.
(defn println-middleware [wrapped-func]
(fn [req]
(println "Request came in!")
(wrapped-func req)))
((println-middleware my-route) request) ;=> response
Und wenn wir etwas tun müssen, bevor auch println-middleware
die Anfrage kommt, dann können wir es wickeln wieder:
((outer-middleware (println-middleware my-routes)) request) ;=> response
Der Schlüssel ist, dass my-routes
, genau wie Ihre my-handler
, ist die einzige benannt Funktion, die die Anfrage tatsächlich als Argument akzeptiert.
Eine letzte Demonstration:
(handler3 (handler2 (handler1 request))) ;=> response
((middleware1 (middleware2 (middleware3 handler1))) request) ;=> response
Ich schreibe so viel, weil ich mitfühlen kann. Aber scroll zurück zu meinem ersten middleware
Beispiel und hoffentlich macht es mehr Sinn.