From 61b0e13581c6334e329511afd919412316918973 Mon Sep 17 00:00:00 2001 From: Bruno do Nascimento Maciel Date: Sun, 11 Jan 2026 11:16:54 -0300 Subject: [PATCH 1/3] implementation --- project.clj | 2 +- src/service_component/interceptors.clj | 16 ++++++++++++---- test/integration/service_component_test.clj | 6 +++--- .../unit/service_component/interceptors_test.clj | 14 ++++++++++++++ 4 files changed, 30 insertions(+), 8 deletions(-) diff --git a/project.clj b/project.clj index ab359ec..bba1ca1 100644 --- a/project.clj +++ b/project.clj @@ -1,4 +1,4 @@ -(defproject net.clojars.macielti/service-component "6.4.3" +(defproject net.clojars.macielti/service-component "7.4.3" :description "Service Component is a Pedestal service Integrant component" diff --git a/src/service_component/interceptors.clj b/src/service_component/interceptors.clj index f613a3c..b68044c 100644 --- a/src/service_component/interceptors.clj +++ b/src/service_component/interceptors.clj @@ -7,6 +7,7 @@ [io.pedestal.interceptor :as pedestal.interceptor] [io.pedestal.interceptor.error :as error] [schema.coerce :as coerce] + [schema.core] [schema.utils] [service-component.error :as common-error]) (:import (java.time LocalDate))) @@ -35,17 +36,24 @@ :enter (fn [context] (assoc-in context [:request :components] system-components))})) +(defn ^:private json-matcher + [schema] + (or (when (and (instance? schema.core.EqSchema schema) + (keyword? (:v schema))) + (fn [x] (if (string? x) (keyword x) x))) + (coerce/json-coercion-matcher schema))) + (defn wire-in-body-schema [schema] (pedestal.interceptor/interceptor {:name ::schema-body-in-interceptor :enter (fn [{{:keys [json-params]} :request :as context}] - (let [coercer-fn (coerce/coercer schema coerce/json-coercion-matcher) + (let [coercer-fn (coerce/coercer schema json-matcher) coercion-result (coercer-fn json-params)] (when (schema.utils/error? coercion-result) (common-error/http-friendly-exception 422 - "invalid-schema-in" - "The system detected that the received data is invalid" - (-> (schema.utils/error-val coercion-result) h/explain))) + "invalid-request-body-payload" + "The system detected that the received data is invalid." + (-> (schema.utils/error-val coercion-result) h/explain str))) (assoc-in context [:request :json-params] coercion-result)))})) (def http-request-in-handle-timing-interceptor diff --git a/test/integration/service_component_test.clj b/test/integration/service_component_test.clj index c990d2d..a59cc1f 100644 --- a/test/integration/service_component_test.clj +++ b/test/integration/service_component_test.clj @@ -56,14 +56,14 @@ (reset! test-state nil) (is (match? {:status 422 :headers {"Content-Type" "application/json;charset=UTF-8"} - :body "{\"error\":\"invalid-schema-in\",\"message\":\"The system detected that the received data is invalid\",\"detail\":{\"test\":\"Missing required key\"}}"} + :body "{\"error\":\"invalid-request-body-payload\",\"message\":\"The system detected that the received data is invalid.\",\"detail\":\"{:test \\\"Missing required key\\\"}\"}"} (test/response-for connector :post "/schema-validation-interceptor-test" :headers {:content-type "application/json"} :body (json/encode {})))) (is (match? {:status 422 :headers {"Content-Type" "application/json;charset=UTF-8"} - :body "{\"error\":\"invalid-schema-in\",\"message\":\"The system detected that the received data is invalid\",\"detail\":{\"hello\":\"Invalid key.\",\"test\":\"Missing required key\"}}"} + :body "{\"error\":\"invalid-request-body-payload\",\"message\":\"The system detected that the received data is invalid.\",\"detail\":\"{:hello \\\"Invalid key.\\\", :test \\\"Missing required key\\\"}\"}"} (test/response-for connector :post "/schema-validation-interceptor-test" :headers {:content-type "application/json"} :body (json/encode {:hello :world})))) @@ -71,7 +71,7 @@ (reset! test-state nil) (is (match? {:status 422 :headers {"Content-Type" "application/json;charset=UTF-8"} - :body "{\"error\":\"invalid-schema-in\",\"message\":\"The system detected that the received data is invalid\",\"detail\":\"The value must be a map, but was '' instead.\"}"} + :body "{\"error\":\"invalid-request-body-payload\",\"message\":\"The system detected that the received data is invalid.\",\"detail\":\"The value must be a map, but was '' instead.\"}"} (test/response-for connector :post "/schema-validation-interceptor-test"))) (reset! test-state nil) diff --git a/test/unit/service_component/interceptors_test.clj b/test/unit/service_component/interceptors_test.clj index 9005b66..7339193 100644 --- a/test/unit/service_component/interceptors_test.clj +++ b/test/unit/service_component/interceptors_test.clj @@ -33,3 +33,17 @@ (is (match? {:request {:query-params {:reference-date (LocalDate/of 1998 12 26)}}} (chain/execute {:request {:query-params {:reference-date "1998-12-26"}}} [(interceptors/query-params-schema QueryParamsWithDate)])))) + +(schema.core/defschema EqKeywordSchema + {:type (schema.core/eq :hello-world)}) + +(s/deftest wire-in-body-schema-test + (is (match? {:request {:json-params {:type :hello-world}}} + (chain/execute {:request {:json-params {:type "hello-world"}}} [(interceptors/wire-in-body-schema EqKeywordSchema)]))) + + (let [ex (is (thrown? ExceptionInfo (chain/execute {:request {:json-params {:type "test"}}} [(interceptors/wire-in-body-schema EqKeywordSchema)])))] + (is (match? {:status 422 + :error "invalid-request-body-payload" + :message "The system detected that the received data is invalid." + :detail "{:type [not [= :hello-world :test]]}"} + (ex-data ex))))) From dac8b0fb57a521f1ec3d0c29905dade2ce40a01b Mon Sep 17 00:00:00 2001 From: Bruno do Nascimento Maciel Date: Sun, 11 Jan 2026 11:20:50 -0300 Subject: [PATCH 2/3] update changelog --- CHANGELOG.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1a6056e..92f7d42 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,17 @@ All notable changes to this project will be documented in this file. This change log follows the conventions of [keepachangelog.com](http://keepachangelog.com/). +## 7.4.3 - 2026-01-11 + +### Changed + +- Breaking Change: Error handling for request body validation has been updated. + - The error code for schema validation failures is now invalid-request-body-payload. + - Error messages for invalid request bodies are improved for clarity. + - Error details in responses are now consistently stringified. +- Schema Coercion: String values in JSON request bodies are now automatically coerced to keywords when the schema + expects a keyword, improving compatibility with EqSchema. + ## 6.4.3 - 2026-01-02 ### Added From 765cd6272e55df000683b8cbdbc5660177d5229f Mon Sep 17 00:00:00 2001 From: Bruno do Nascimento Maciel Date: Sun, 11 Jan 2026 11:22:15 -0300 Subject: [PATCH 3/3] improve changes description --- CHANGELOG.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 92f7d42..e9092c7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,11 +8,11 @@ of [keepachangelog.com](http://keepachangelog.com/). ### Changed - Breaking Change: Error handling for request body validation has been updated. - - The error code for schema validation failures is now invalid-request-body-payload. + - The error code for schema validation failures is now `"invalid-request-body-payload"`. - Error messages for invalid request bodies are improved for clarity. - Error details in responses are now consistently stringified. - Schema Coercion: String values in JSON request bodies are now automatically coerced to keywords when the schema - expects a keyword, improving compatibility with EqSchema. + expects a keyword, improving compatibility with `EqSchema`. ## 6.4.3 - 2026-01-02