Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 25 additions & 3 deletions src/service_component/interceptors.clj
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,31 @@

(defn ^:private json-matcher
[schema]
(or (when (and (instance? schema.core.EqSchema schema)
(keyword? (:v schema)))
(fn [x] (if (string? x) (keyword x) x)))
(or (when (instance? schema.core.EqSchema schema)
(when (keyword? (:v schema))
(fn [x] (if (string? x) (keyword x) x))))

(when (instance? schema.core.ConditionalSchema schema)
(fn [data]
(let [preds-and-schemas-vec (:preds-and-schemas schema)
;; Find the schema that corresponds to the first matching predicate
schema-to-use (loop [ps-pairs (partition-all 2 preds-and-schemas-vec)]
(if-let [[p s] (first ps-pairs)]
(cond
;; Case 1: The 'else' clause. `s` is nil, so `p` is the schema.
(nil? s) p
;; Case 2: The predicate `p` matches the data. Return the schema `s`.
(p data) s
;; Case 3: No match, try the next pair.
:else (recur (next ps-pairs)))
;; Default case if loop finishes (shouldn't happen with valid s/conditional)
nil))]
;; If we found a schema, create a coercer for it and run it.
(if schema-to-use
((coerce/coercer schema-to-use json-matcher) data)
;; Otherwise, return the data as-is.
data))))

(coerce/json-coercion-matcher schema)))

(defn wire-in-body-schema [schema]
Expand Down
6 changes: 6 additions & 0 deletions test/unit/service_component/interceptors_test.clj
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,16 @@
(schema.core/defschema EqKeywordSchema
{:type (schema.core/eq :hello-world)})

(schema.core/defschema ConditionalEqKeywordSchema
(schema.core/conditional #(= (:type #p %) :hello-world) EqKeywordSchema))

(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)])))

(is (match? {:request {:json-params {:type :hello-world}}}
(chain/execute {:request {:json-params {:type "hello-world"}}} [(interceptors/wire-in-body-schema ConditionalEqKeywordSchema)])))

(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"
Expand Down
Loading