diff --git a/examples/http-swagger/src/example/server.clj b/examples/http-swagger/src/example/server.clj index 2de6d8fc..bf2c5d55 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] @@ -113,10 +113,10 @@ :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 :exception pretty/exception - :data {:coercion spec-coercion/coercion + :data {:coercion reitit.coercion.spec/coercion :muuntaja m/instance :interceptors [;; swagger feature swagger/swagger-feature @@ -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 51e16059..e3285dd2 100644 --- a/examples/pedestal-swagger/src/example/server.clj +++ b/examples/pedestal-swagger/src/example/server.clj @@ -1,16 +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.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])) @@ -76,15 +80,22 @@ {:status 200 :body {:total (+ x y)}})}}]]] - {;;:reitit.interceptor/transform dev/print-context-diffs - :data {:coercion spec-coercion/coercion + {;: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 + :exception pretty/exception + :data {:coercion reitit.coercion.spec/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 @@ -98,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 514cb8f8..4a807f75 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 @@ -93,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 [] 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 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 ([_]) ([_ _]))})))))