From 6d263ae1b68cc57de8b8bdad5388607677527bca Mon Sep 17 00:00:00 2001 From: Tommi Reiman Date: Sat, 11 May 2019 10:25:09 +0300 Subject: [PATCH 1/4] Test Pedestal error mapping, add dev helpers --- .../pedestal-swagger/src/example/server.clj | 15 +++++++- .../reitit-pedestal/src/reitit/pedestal.clj | 38 +++++++++++-------- test/clj/reitit/pedestal_test.clj | 23 +++++++++++ 3 files changed, 59 insertions(+), 17 deletions(-) create mode 100644 test/clj/reitit/pedestal_test.clj diff --git a/examples/pedestal-swagger/src/example/server.clj b/examples/pedestal-swagger/src/example/server.clj index 51e16059..c5f18623 100644 --- a/examples/pedestal-swagger/src/example/server.clj +++ b/examples/pedestal-swagger/src/example/server.clj @@ -9,8 +9,12 @@ [reitit.coercion.spec :as spec-coercion] [reitit.http.interceptors.parameters :as parameters] [reitit.http.interceptors.muuntaja :as muuntaja] + [reitit.http.interceptors.exception :as exception] [reitit.http.interceptors.multipart :as multipart] [reitit.http.interceptors.dev :as dev] + [reitit.dev.pretty :as pretty] + [spec-tools.spell :as spell] + [reitit.http.spec :as spec] [clojure.core.async :as a] [clojure.java.io :as io] [muuntaja.core :as m])) @@ -76,15 +80,22 @@ {:status 200 :body {:total (+ x y)}})}}]]] - {;;:reitit.interceptor/transform dev/print-context-diffs + {;:reitit.interceptor/transform dev/print-context-diffs ;; pretty context diffs + ;;:validate spec/validate ;; enable spec validation for route data + ;;:reitit.spec/wrap spell/closed ;; strict top-level validation (alpha) + :exception pretty/exception :data {:coercion spec-coercion/coercion :muuntaja m/instance - :interceptors [;; query-params & form-params + :interceptors [;; swagger feature + swagger/swagger-feature + ;; query-params & form-params (parameters/parameters-interceptor) ;; content-negotiation (muuntaja/format-negotiate-interceptor) ;; encoding response body (muuntaja/format-response-interceptor) + ;; exception handling + (exception/exception-interceptor) ;; decoding request body (muuntaja/format-request-interceptor) ;; coercing response bodys diff --git a/modules/reitit-pedestal/src/reitit/pedestal.clj b/modules/reitit-pedestal/src/reitit/pedestal.clj index 28c21e0a..51c9a45b 100644 --- a/modules/reitit-pedestal/src/reitit/pedestal.clj +++ b/modules/reitit-pedestal/src/reitit/pedestal.clj @@ -4,18 +4,18 @@ [io.pedestal.http :as http] [reitit.interceptor] [reitit.http]) - (:import (reitit.interceptor Executor))) + (:import (reitit.interceptor Executor) + (java.lang.reflect Method))) -(defn- arity [f] +(defn- arities [f] (->> (class f) .getDeclaredMethods (filter #(= "invoke" (.getName %))) - first - .getParameterTypes - alength)) + (map #(alength (.getParameterTypes ^Method %))) + (set))) -(defn- error-with-arity-1? [{error-fn :error}] - (and error-fn (= 1 (arity error-fn)))) +(defn- error-without-arity-2? [{error-fn :error}] + (and error-fn (not (contains? (arities error-fn) 2)))) (defn- error-arity-2->1 [error] (fn [context ex] @@ -26,9 +26,23 @@ (dissoc :error)) context)))) -(defn wrap-error-arity-2->1 [interceptor] +(defn- wrap-error-arity-2->1 [interceptor] (update interceptor :error error-arity-2->1)) +(defn ->interceptor [interceptor] + (cond + (interceptor/interceptor? interceptor) + interceptor + (seq (select-keys interceptor [:enter :leave :error])) + (interceptor/interceptor + (if (error-without-arity-2? interceptor) + (wrap-error-arity-2->1 interceptor) + interceptor)))) + +;; +;; Public API +;; + (def pedestal-executor (reify Executor @@ -36,13 +50,7 @@ (->> interceptors (map (fn [{:keys [::interceptor/handler] :as interceptor}] (or handler interceptor))) - (map (fn [interceptor] - (if (interceptor/interceptor? interceptor) - interceptor - (interceptor/interceptor - (if (error-with-arity-1? interceptor) - (wrap-error-arity-2->1 interceptor) - interceptor))))))) + (keep ->interceptor))) (enqueue [_ context interceptors] (chain/enqueue context interceptors)))) diff --git a/test/clj/reitit/pedestal_test.clj b/test/clj/reitit/pedestal_test.clj new file mode 100644 index 00000000..f1942fe9 --- /dev/null +++ b/test/clj/reitit/pedestal_test.clj @@ -0,0 +1,23 @@ +(ns reitit.pedestal-test + (:require [clojure.test :refer [deftest testing is]] + [reitit.pedestal :as pedestal])) + +(deftest arities-test + (is (= #{0} (#'pedestal/arities (fn [])))) + (is (= #{1} (#'pedestal/arities (fn [_])))) + (is (= #{0 1 2} (#'pedestal/arities (fn ([]) ([_]) ([_ _])))))) + +(deftest interceptor-test + (testing "wihtout :enter, :leave or :error are stripped" + (is (nil? (pedestal/->interceptor {:name ::kikka})))) + (testing ":error arities are wrapped" + (let [has-2-arity-error? (fn [interceptor] + (-> interceptor + (pedestal/->interceptor) + (:error) + (#'pedestal/arities) + (contains? 2)))] + (is (has-2-arity-error? {:error (fn [_])})) + (is (has-2-arity-error? {:error (fn [_ _])})) + (is (has-2-arity-error? {:error (fn [_ _ _])})) + (is (has-2-arity-error? {:error (fn ([_]) ([_ _]))}))))) From 6efe4f612bdcfb43b04282df4724d52f9db0a65c Mon Sep 17 00:00:00 2001 From: Tommi Reiman Date: Sat, 11 May 2019 10:25:19 +0300 Subject: [PATCH 2/4] Comment out spec-validation --- examples/http-swagger/src/example/server.clj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/http-swagger/src/example/server.clj b/examples/http-swagger/src/example/server.clj index 2de6d8fc..bd20c1fa 100644 --- a/examples/http-swagger/src/example/server.clj +++ b/examples/http-swagger/src/example/server.clj @@ -113,8 +113,8 @@ :body {:total (- x y)}})}}]]] {;:reitit.interceptor/transform dev/print-context-diffs ;; pretty context diffs - :validate spec/validate ;; enable spec validation for route data - :reitit.spec/wrap spell/closed ;; strict top-level validation (alpha) + ;;:validate spec/validate ;; enable spec validation for route data + ;;:reitit.spec/wrap spell/closed ;; strict top-level validation (alpha) :exception pretty/exception :data {:coercion spec-coercion/coercion :muuntaja m/instance From 1d72575e48e4c5fcde1c6b040cd8bfc5bec3077d Mon Sep 17 00:00:00 2001 From: Tommi Reiman Date: Sat, 11 May 2019 14:25:25 +0300 Subject: [PATCH 3/4] Update swagger-examples to have closed-spec validation --- examples/http-swagger/src/example/server.clj | 12 ++++++------ examples/pedestal-swagger/src/example/server.clj | 12 ++++++------ .../ring-spec-swagger/src/example/server.clj | 16 +++++++++++++--- examples/ring-swagger/src/example/server.clj | 14 +++++++++++--- 4 files changed, 36 insertions(+), 18 deletions(-) diff --git a/examples/http-swagger/src/example/server.clj b/examples/http-swagger/src/example/server.clj index bd20c1fa..af2920a0 100644 --- a/examples/http-swagger/src/example/server.clj +++ b/examples/http-swagger/src/example/server.clj @@ -1,18 +1,18 @@ (ns example.server (:require [reitit.ring :as ring] [reitit.http :as http] + [reitit.coercion.spec] [reitit.swagger :as swagger] [reitit.swagger-ui :as swagger-ui] [reitit.http.coercion :as coercion] - [reitit.coercion.spec :as spec-coercion] + [reitit.dev.pretty :as pretty] + [reitit.interceptor.sieppari :as sieppari] [reitit.http.interceptors.parameters :as parameters] [reitit.http.interceptors.muuntaja :as muuntaja] [reitit.http.interceptors.exception :as exception] [reitit.http.interceptors.multipart :as multipart] - [reitit.http.spec :as spec] [reitit.http.interceptors.dev :as dev] - [reitit.interceptor.sieppari :as sieppari] - [reitit.dev.pretty :as pretty] + [reitit.http.spec :as spec] [spec-tools.spell :as spell] [ring.adapter.jetty :as jetty] [aleph.http :as client] @@ -114,9 +114,9 @@ {;:reitit.interceptor/transform dev/print-context-diffs ;; pretty context diffs ;;:validate spec/validate ;; enable spec validation for route data - ;;:reitit.spec/wrap spell/closed ;; strict top-level validation (alpha) + ;;:reitit.spec/wrap spell/closed ;; strict top-level validation :exception pretty/exception - :data {:coercion spec-coercion/coercion + :data {:coercion reitit.coercion.spec/coercion :muuntaja m/instance :interceptors [;; swagger feature swagger/swagger-feature diff --git a/examples/pedestal-swagger/src/example/server.clj b/examples/pedestal-swagger/src/example/server.clj index c5f18623..c30f9d24 100644 --- a/examples/pedestal-swagger/src/example/server.clj +++ b/examples/pedestal-swagger/src/example/server.clj @@ -1,20 +1,20 @@ (ns example.server (:require [io.pedestal.http :as server] - [reitit.pedestal :as pedestal] [reitit.ring :as ring] [reitit.http :as http] + [reitit.coercion.spec] [reitit.swagger :as swagger] [reitit.swagger-ui :as swagger-ui] [reitit.http.coercion :as coercion] - [reitit.coercion.spec :as spec-coercion] [reitit.http.interceptors.parameters :as parameters] [reitit.http.interceptors.muuntaja :as muuntaja] [reitit.http.interceptors.exception :as exception] [reitit.http.interceptors.multipart :as multipart] [reitit.http.interceptors.dev :as dev] - [reitit.dev.pretty :as pretty] - [spec-tools.spell :as spell] [reitit.http.spec :as spec] + [spec-tools.spell :as spell] + [io.pedestal.http :as server] + [reitit.pedestal :as pedestal] [clojure.core.async :as a] [clojure.java.io :as io] [muuntaja.core :as m])) @@ -82,9 +82,9 @@ {;:reitit.interceptor/transform dev/print-context-diffs ;; pretty context diffs ;;:validate spec/validate ;; enable spec validation for route data - ;;:reitit.spec/wrap spell/closed ;; strict top-level validation (alpha) + ;;:reitit.spec/wrap spell/closed ;; strict top-level validation :exception pretty/exception - :data {:coercion spec-coercion/coercion + :data {:coercion reitit.coercion.spec/coercion :muuntaja m/instance :interceptors [;; swagger feature swagger/swagger-feature diff --git a/examples/ring-spec-swagger/src/example/server.clj b/examples/ring-spec-swagger/src/example/server.clj index 514cb8f8..eca70e2b 100644 --- a/examples/ring-spec-swagger/src/example/server.clj +++ b/examples/ring-spec-swagger/src/example/server.clj @@ -1,13 +1,17 @@ (ns example.server (:require [reitit.ring :as ring] + [reitit.coercion.spec] [reitit.swagger :as swagger] [reitit.swagger-ui :as swagger-ui] [reitit.ring.coercion :as coercion] - [reitit.coercion.spec] + [reitit.dev.pretty :as pretty] [reitit.ring.middleware.muuntaja :as muuntaja] [reitit.ring.middleware.exception :as exception] [reitit.ring.middleware.multipart :as multipart] [reitit.ring.middleware.parameters :as parameters] + [reitit.ring.middleware.dev :as dev] + [reitit.ring.spec :as spec] + [spec-tools.spell :as spell] [ring.adapter.jetty :as jetty] [muuntaja.core :as m] [clojure.spec.alpha :as s] @@ -72,9 +76,15 @@ {:status 200 :body {:total (+ x y)}})}}]]] - {:data {:coercion reitit.coercion.spec/coercion + {;;:reitit.middleware/transform dev/print-request-diffs ;; pretty diffs + ;;:validate spec/validate ;; enable spec validation for route data + ;;:reitit.spec/wrap spell/closed ;; strict top-level validation + :exception pretty/exception + :data {:coercion reitit.coercion.spec/coercion :muuntaja m/instance - :middleware [;; query-params & form-params + :middleware [;; swagger feature + swagger/swagger-feature + ;; query-params & form-params parameters/parameters-middleware ;; content-negotiation muuntaja/format-negotiate-middleware diff --git a/examples/ring-swagger/src/example/server.clj b/examples/ring-swagger/src/example/server.clj index 17628614..dd661ce7 100644 --- a/examples/ring-swagger/src/example/server.clj +++ b/examples/ring-swagger/src/example/server.clj @@ -1,14 +1,17 @@ (ns example.server (:require [reitit.ring :as ring] + [reitit.coercion.spec] [reitit.swagger :as swagger] [reitit.swagger-ui :as swagger-ui] [reitit.ring.coercion :as coercion] - [reitit.coercion.spec] + [reitit.dev.pretty :as pretty] [reitit.ring.middleware.muuntaja :as muuntaja] [reitit.ring.middleware.exception :as exception] [reitit.ring.middleware.multipart :as multipart] [reitit.ring.middleware.parameters :as parameters] [reitit.ring.middleware.dev :as dev] + [reitit.ring.spec :as spec] + [spec-tools.spell :as spell] [ring.adapter.jetty :as jetty] [muuntaja.core :as m] [clojure.java.io :as io])) @@ -61,10 +64,15 @@ {:status 200 :body {:total (+ x y)}})}}]]] - {;;:reitit.middleware/transform dev/print-request-diffs + {;;:reitit.middleware/transform dev/print-request-diffs ;; pretty diffs + ;;:validate spec/validate ;; enable spec validation for route data + ;;:reitit.spec/wrap spell/closed ;; strict top-level validation + :exception pretty/exception :data {:coercion reitit.coercion.spec/coercion :muuntaja m/instance - :middleware [;; query-params & form-params + :middleware [;; swagger feature + swagger/swagger-feature + ;; query-params & form-params parameters/parameters-middleware ;; content-negotiation muuntaja/format-negotiate-middleware From a696eaa32a6a524f490c9109143130537b8fcbc9 Mon Sep 17 00:00:00 2001 From: Tommi Reiman Date: Sat, 11 May 2019 14:27:08 +0300 Subject: [PATCH 4/4] Add sorting to swagger-ui --- examples/http-swagger/src/example/server.clj | 3 ++- examples/pedestal-swagger/src/example/server.clj | 3 ++- examples/ring-spec-swagger/src/example/server.clj | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/examples/http-swagger/src/example/server.clj b/examples/http-swagger/src/example/server.clj index af2920a0..bf2c5d55 100644 --- a/examples/http-swagger/src/example/server.clj +++ b/examples/http-swagger/src/example/server.clj @@ -139,7 +139,8 @@ (ring/routes (swagger-ui/create-swagger-ui-handler {:path "/" - :config {:validatorUrl nil}}) + :config {:validatorUrl nil + :operationsSorter "alpha"}}) (ring/create-default-handler)) {:executor sieppari/executor})) diff --git a/examples/pedestal-swagger/src/example/server.clj b/examples/pedestal-swagger/src/example/server.clj index c30f9d24..e3285dd2 100644 --- a/examples/pedestal-swagger/src/example/server.clj +++ b/examples/pedestal-swagger/src/example/server.clj @@ -109,7 +109,8 @@ (ring/routes (swagger-ui/create-swagger-ui-handler {:path "/" - :config {:validatorUrl nil}}) + :config {:validatorUrl nil + :operationsSorter "alpha"}}) (ring/create-resource-handler) (ring/create-default-handler)))) diff --git a/examples/ring-spec-swagger/src/example/server.clj b/examples/ring-spec-swagger/src/example/server.clj index eca70e2b..4a807f75 100644 --- a/examples/ring-spec-swagger/src/example/server.clj +++ b/examples/ring-spec-swagger/src/example/server.clj @@ -103,7 +103,8 @@ (ring/routes (swagger-ui/create-swagger-ui-handler {:path "/" - :config {:validatorUrl nil}}) + :config {:validatorUrl nil + :operationsSorter "alpha"}}) (ring/create-default-handler)))) (defn start []