From 20b7cabed744c423d950f27746b5d87f5c6fbb3e Mon Sep 17 00:00:00 2001 From: Tommi Reiman Date: Tue, 3 Aug 2021 08:46:51 +0300 Subject: [PATCH 1/2] Fix Malli encoding,, #498 --- .../src/reitit/coercion/malli.cljc | 23 ++++----- test/cljc/reitit/ring_coercion_test.cljc | 50 ++++++++++++++++++- 2 files changed, 59 insertions(+), 14 deletions(-) diff --git a/modules/reitit-malli/src/reitit/coercion/malli.cljc b/modules/reitit-malli/src/reitit/coercion/malli.cljc index 23ec65b9..ee4a4bdc 100644 --- a/modules/reitit-malli/src/reitit/coercion/malli.cljc +++ b/modules/reitit-malli/src/reitit/coercion/malli.cljc @@ -34,7 +34,7 @@ (def json-transformer-provider (-provider (mt/json-transformer))) (def default-transformer-provider (-provider nil)) -(defn- -coercer [schema type transformers f encoder {:keys [validate enabled options]}] +(defn- -coercer [schema type transformers f {:keys [validate enabled options]}] (if schema (let [->coercer (fn [t] (let [decoder (if t (m/decoder schema options t) identity) @@ -48,7 +48,6 @@ (-explain [_ value] (explainer value))))) {:keys [formats default]} (transformers type) default-coercer (->coercer default) - encode (or encoder (fn [value _format] value)) format-coercers (some->> (for [[f t] formats] [f (->coercer t)]) (filter second) (seq) (into {})) get-coercer (cond format-coercers (fn [format] (or (get format-coercers format) default-coercer)) default-coercer (constantly default-coercer))] @@ -66,14 +65,14 @@ value)) ;; encode: decode -> validate -> encode (fn [value format] - (if-let [coercer (get-coercer format)] - (let [transformed (-decode coercer value)] + (let [transformed (-decode default-coercer value)] + (if-let [coercer (get-coercer format)] (if (-validate coercer transformed) - (encode transformed format) + (-encode coercer transformed) (let [error (-explain coercer transformed)] (coercion/map->CoercionError - (assoc error :transformed transformed))))) - value))))))) + (assoc error :transformed transformed)))) + value)))))))) ;; ;; swagger @@ -106,11 +105,13 @@ ;; public api ;; +;; TODO: this is much too compöex (def default-options {:transformers {:body {:default default-transformer-provider :formats {"application/json" json-transformer-provider}} :string {:default string-transformer-provider} - :response {:default default-transformer-provider}} + :response {:default default-transformer-provider + :formats {"application/json" json-transformer-provider}}} ;; set of keys to include in error messages :error-keys #{:type :coercion :in :schema :value :errors :humanized #_:transformed} ;; schema identity function (default: close all map schemas) @@ -176,10 +177,8 @@ (seq error-keys) (select-keys error-keys) encode-error (encode-error))) (-request-coercer [_ type schema] - (-coercer (compile schema options) type transformers :decode nil opts)) + (-coercer (compile schema options) type transformers :decode opts)) (-response-coercer [_ schema] - (let [schema (compile schema options) - encoder (-coercer schema :body transformers :encode nil opts)] - (-coercer schema :response transformers :encode encoder opts))))))) + (-coercer (compile schema options) :response transformers :encode opts)))))) (def coercion (create default-options)) diff --git a/test/cljc/reitit/ring_coercion_test.cljc b/test/cljc/reitit/ring_coercion_test.cljc index 3e38029e..fd5448f7 100644 --- a/test/cljc/reitit/ring_coercion_test.cljc +++ b/test/cljc/reitit/ring_coercion_test.cljc @@ -207,6 +207,24 @@ (let [{:keys [status]} (app invalid-request2)] (is (= 500 status)))))))) +(let [app (ring/ring-handler + (ring/router + ["/plus" {:get {:parameters {:query [:map [:x :int]]} + :responses {200 {:body [:map + [:total [:int {:encode/json str + :min 0}]]]}} + :handler (fn [{{{:keys [x]} :query} :parameters}] + {:status 200 + :body {:total (* x x)}})}}] + {:data {:middleware [rrc/coerce-request-middleware + rrc/coerce-response-middleware] + :coercion malli/coercion}}))] + (app {:uri "/plus" + :request-method :get + :muuntaja/request {:format "application/json"} + :muuntaja/response {:format "application/json"} + :query-params {"x" "2"}})) + (deftest malli-coercion-test (let [create (fn [middleware] (ring/ring-handler @@ -397,7 +415,7 @@ (testing "encoding errors" (let [app (->app {:encode-error (fn [error] {:errors (:humanized error)})})] (is (= {:status 400, :body {:errors {:x ["missing required key"]}}} - (app (assoc (->request "closed") :body-params {})))))) + (app (assoc (->request "closed") :body-params {})))))) (testing "when schemas are not closed and extra keys are not stripped" (let [app (->app {:compile (fn [v _] v) :strip-extra-keys false})] @@ -449,7 +467,35 @@ (testing "failed response" (let [{:keys [status body]} (app (->request [{:message "kosh"}]))] (is (= 500 status)) - (is (= :reitit.coercion/response-coercion (:type body)))))))))) + (is (= :reitit.coercion/response-coercion (:type body)))))))) + + (testing "encoding responses" + (let [->app (fn [total-schema] + (ring/ring-handler + (ring/router + ["/total" {:get {:parameters {:query [:map [:x :int]]} + :responses {200 {:body [:map [:total total-schema]]}} + :handler (fn [{{{:keys [x]} :query} :parameters}] + {:status 200 + :body {:total (* x x)}})}}] + {:data {:middleware [rrc/coerce-request-middleware + rrc/coerce-response-middleware] + :coercion malli/coercion}}))) + call (fn [accept total-schema] + ((->app total-schema) {:uri "/total" + :request-method :get + :muuntaja/request {:format "application/json"} + :muuntaja/response {:format accept} + :query-params {"x" "2"}}))] + + (testing "no encoding" + (is (= {:status 200, :body {:total +4}} (call "application/json" :int)))) + + (testing "json encoding" + (is (= {:status 200, :body {:total -4}} (call "application/json" [:int {:encode/json -}])))) + + (testing "edn encoding (nada)" + (is (= {:status 200, :body {:total +4}} (call "application/edn" [:int {:encode/json -}])))))))) #?(:clj (deftest muuntaja-test From 020c424b4e5577ffb01f6dcf6635e0c298f17745 Mon Sep 17 00:00:00 2001 From: Tommi Reiman Date: Tue, 3 Aug 2021 13:24:29 +0300 Subject: [PATCH 2/2] dead code, CHANGELOG --- CHANGELOG.md | 4 ++++ test/cljc/reitit/ring_coercion_test.cljc | 18 ------------------ 2 files changed, 4 insertions(+), 18 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 95a96aae..d49cbb30 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,6 +27,10 @@ We use [Break Versioning][breakver]. The version numbers follow a `.