From ffc36fce369aa6e48ce28e9bae4e69a11c9348bb Mon Sep 17 00:00:00 2001 From: Tommi Reiman Date: Sun, 18 Nov 2018 22:19:30 +0200 Subject: [PATCH] Support composable transformations of mw/interceptor chain * fixes #167 --- CHANGELOG.md | 4 ++++ .../reitit-core/src/reitit/interceptor.cljc | 11 +++++---- .../reitit-core/src/reitit/middleware.cljc | 13 +++++----- test/cljc/reitit/interceptor_test.cljc | 24 +++++++++++++------ test/cljc/reitit/middleware_test.cljc | 7 +++++- 5 files changed, 40 insertions(+), 19 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2924dc91..b64b1820 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ ## UNRELEASED +## `reitit-core` + +* Added support for composing middleware & interceptor transformations, fixes [#167](https://github.com/metosin/reitit/issues/167). + ## `reitit-spec` * Spec problems are exposed as-is into request & response coercion errors, enabling pretty-printers like [expound](https://github.com/bhb/expound) to be used: diff --git a/modules/reitit-core/src/reitit/interceptor.cljc b/modules/reitit-core/src/reitit/interceptor.cljc index f45fe74c..c1829e49 100644 --- a/modules/reitit-core/src/reitit/interceptor.cljc +++ b/modules/reitit-core/src/reitit/interceptor.cljc @@ -110,11 +110,12 @@ ([interceptors data] (chain interceptors data nil)) ([interceptors data {:keys [::transform] :or {transform identity} :as opts}] - (->> interceptors - (keep #(into-interceptor % data opts)) - (transform) - (keep #(into-interceptor % data opts)) - (into [])))) + (let [transform (if (vector? transform) (apply comp (reverse transform)) transform)] + (->> interceptors + (keep #(into-interceptor % data opts)) + (transform) + (keep #(into-interceptor % data opts)) + (into []))))) (defn compile-result ([route opts] diff --git a/modules/reitit-core/src/reitit/middleware.cljc b/modules/reitit-core/src/reitit/middleware.cljc index f429aac1..d9bdc66d 100644 --- a/modules/reitit-core/src/reitit/middleware.cljc +++ b/modules/reitit-core/src/reitit/middleware.cljc @@ -84,12 +84,13 @@ (defn- expand-and-transform [middleware data {:keys [::transform] :or {transform identity} :as opts}] - (->> middleware - (keep #(into-middleware % data opts)) - (into []) - (transform) - (keep #(into-middleware % data opts)) - (into []))) + (let [transform (if (vector? transform) (apply comp (reverse transform)) transform)] + (->> middleware + (keep #(into-middleware % data opts)) + (into []) + (transform) + (keep #(into-middleware % data opts)) + (into [])))) (defn- compile-handler [middleware handler] ((apply comp identity (keep :wrap middleware)) handler)) diff --git a/test/cljc/reitit/interceptor_test.cljc b/test/cljc/reitit/interceptor_test.cljc index 639db51d..3eed9ae7 100644 --- a/test/cljc/reitit/interceptor_test.cljc +++ b/test/cljc/reitit/interceptor_test.cljc @@ -222,19 +222,29 @@ (enter ::kerran) (enter ::avaruus)] :handler handler}] - options)))] + options))) + inject-debug (fn [interceptors] + (concat + (interleave (butlast interceptors) (repeat debug-i)) + [(last interceptors)])) + sort-interceptors (fn [interceptors] + (concat + (sort-by :name (butlast interceptors)) + [(last interceptors)]))] (testing "by default, all interceptors are applied in order" (let [app (create nil)] (is (= [::olipa ::kerran ::avaruus :ok] (app "/ping"))))) (testing "interceptors can be re-ordered" - (let [app (create {::interceptor/transform (fn [interceptors] - (concat - (sort-by :name (butlast interceptors)) - [(last interceptors)]))})] + (let [app (create {::interceptor/transform sort-interceptors})] (is (= [::avaruus ::kerran ::olipa :ok] (app "/ping"))))) (testing "adding debug interceptor between interceptors" - (let [app (create {::interceptor/transform #(interleave % (repeat debug-i))})] - (is (= [::olipa ::debug ::kerran ::debug ::avaruus ::debug :ok] (app "/ping"))))))) + (let [app (create {::interceptor/transform inject-debug})] + (is (= [::olipa ::debug ::kerran ::debug ::avaruus ::debug :ok] (app "/ping"))))) + + (testing "vector of transformations" + (let [app (create {::interceptor/transform [inject-debug + sort-interceptors]})] + (is (= [::avaruus ::debug ::debug ::debug ::kerran ::olipa :ok] (app "/ping"))))))) diff --git a/test/cljc/reitit/middleware_test.cljc b/test/cljc/reitit/middleware_test.cljc index 11f75c7f..7933ed2b 100644 --- a/test/cljc/reitit/middleware_test.cljc +++ b/test/cljc/reitit/middleware_test.cljc @@ -254,4 +254,9 @@ (testing "adding debug middleware between middleware" (let [app (create {::middleware/transform #(interleave % (repeat debug-mw))})] - (is (= [::olipa ::debug ::kerran ::debug ::avaruus ::debug :ok] (app "/ping"))))))) + (is (= [::olipa ::debug ::kerran ::debug ::avaruus ::debug :ok] (app "/ping"))))) + + (testing "vector of transformations" + (let [app (create {::middleware/transform [#(interleave % (repeat debug-mw)) + (partial sort-by :name)]})] + (is (= [::avaruus ::debug ::debug ::debug ::kerran ::olipa :ok] (app "/ping")))))))