From 0454e8914f1a03520ec9ced3d50d8ac362751a83 Mon Sep 17 00:00:00 2001 From: Casey Link Date: Tue, 29 Apr 2025 14:00:33 +0200 Subject: [PATCH 1/3] Apply router options to top-level middleware chain Middleware supplied to the `ring-handler` function could not be resolved from the middleware registry, because the router options (which contain the registry) were not being propagated. Fixes #738 --- modules/reitit-ring/src/reitit/ring.cljc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/reitit-ring/src/reitit/ring.cljc b/modules/reitit-ring/src/reitit/ring.cljc index 7feb5a54..bb48f8f0 100644 --- a/modules/reitit-ring/src/reitit/ring.cljc +++ b/modules/reitit-ring/src/reitit/ring.cljc @@ -370,7 +370,7 @@ ([router default-handler {:keys [middleware inject-match? inject-router?] :or {inject-match? true, inject-router? true}}] (let [default-handler (or default-handler (fn ([_]) ([_ respond _] (respond nil)))) - wrap (if middleware (partial middleware/chain middleware) identity) + wrap (if middleware #(middleware/chain middleware % nil (r/options router)) identity) enrich-request (create-enrich-request inject-match? inject-router?) enrich-default-request (create-enrich-default-request inject-router?)] (with-meta From d8092915536827b5b0d42022458d97b9547dfe8e Mon Sep 17 00:00:00 2001 From: Joel Kaasinen Date: Mon, 13 Oct 2025 09:00:04 +0300 Subject: [PATCH 2/3] test: ring-handler middleware from registry inside router --- test/cljc/reitit/ring_test.cljc | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/test/cljc/reitit/ring_test.cljc b/test/cljc/reitit/ring_test.cljc index 1825dee7..e3ea297a 100644 --- a/test/cljc/reitit/ring_test.cljc +++ b/test/cljc/reitit/ring_test.cljc @@ -114,6 +114,25 @@ (is (= {:status 200, :body [:top :api :ok]} (app {:uri "/api/get" :request-method :get})))))) + (testing "middleware from registry" + (let [router (ring/router + ["/api" {:middleware [:mw-foo]} + ["/get" {:middleware [[:mw :inner]] + :get handler}]] + {::middleware/registry {:mw mw + :mw-foo #(mw % :foo)}}) + app (ring/ring-handler router nil {:middleware [[:mw :top]]})] + + (testing "router can be extracted" + (is (= router (ring/get-router app)))) + + (testing "not found" + (is (= nil (app {:uri "/favicon.ico"})))) + + (testing "on match" + (is (= {:status 200, :body [:top :foo :inner :ok]} + (app {:uri "/api/get" :request-method :get})))))) + (testing "named routes" (let [router (ring/router [["/api" @@ -743,7 +762,7 @@ (is (= (redirect "/docs/index.html") response))) (let [response (app (request "/foobar"))] (is (= 404 (:status response))))))) - + (testing "with additional mime types" (let [app (ring/ring-handler (ring/router From 2f22838820fdbd880dbbce09a5bbaae5a3392939 Mon Sep 17 00:00:00 2001 From: Joel Kaasinen Date: Mon, 13 Oct 2025 09:09:11 +0300 Subject: [PATCH 3/3] doc: using middleware from registry at ring-handler level --- doc/ring/middleware_registry.md | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/doc/ring/middleware_registry.md b/doc/ring/middleware_registry.md index cb714383..2780970d 100644 --- a/doc/ring/middleware_registry.md +++ b/doc/ring/middleware_registry.md @@ -2,7 +2,7 @@ The `:middleware` syntax in `reitit-ring` also supports Keywords. Keywords are looked up from the Middleware Registry, which is a map of `keyword => IntoMiddleware`. Middleware registry should be stored under key `:reitit.middleware/registry` in the router options. If a middleware keyword isn't found in the registry, router creation fails fast with a descriptive error message. -## Examples +## Examples Application using middleware defined in the Middleware Registry: @@ -52,6 +52,20 @@ Router creation fails fast if the registry doesn't contain the middleware: ;| :bonus | reitit.ring_test$wrap_bonus@59fddabb | ``` +Middleware defined in the registry can also be used on the `ring-handler` level: + +```clj +(def app + (ring/ring-handler + (ring/router + ["/api" + ["/bonus" {:get (fn [{:keys [bonus]}] + {:status 200, :body {:bonus bonus}})}]] + {::middleware/registry {:bonus wrap-bonus}}) + nil + {:middleware [[:bonus 15]]})) +``` + ## When to use the registry? Middleware as Keywords helps to keep the routes (all but handlers) as literal data (i.e. data that evaluates to itself), enabling the routes to be persisted in external formats like EDN-files and databases. Duct is a good example, where the [middleware can be referenced from EDN-files](https://github.com/duct-framework/duct/wiki/Configuration). It should be easy to make Duct configuration a Middleware Registry in `reitit-ring`.