mirror of
https://github.com/metosin/reitit.git
synced 2026-01-01 14:18:25 +00:00
Compare commits
13 commits
211e434fcf
...
a81972eb70
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a81972eb70 | ||
|
|
c3a152a44e | ||
|
|
c0bc789863 | ||
|
|
78aba57d2d | ||
|
|
451b286f1d | ||
|
|
eb06404f1e | ||
|
|
af7313bd9b | ||
|
|
ea58100fec | ||
|
|
a4576cc622 | ||
|
|
9d88d92241 | ||
|
|
d16aac673e | ||
|
|
dede2db213 | ||
|
|
f1ade4b089 |
7 changed files with 101 additions and 4 deletions
|
|
@ -16,6 +16,7 @@ We use [Break Versioning][breakver]. The version numbers follow a `<major>.<mino
|
||||||
|
|
||||||
* Improve & document how response schemas get picked in per-content-type coercion. See [docs](./doc/ring/coercion.md#per-content-type-coercion). [#745](https://github.com/metosin/reitit/issues/745).
|
* Improve & document how response schemas get picked in per-content-type coercion. See [docs](./doc/ring/coercion.md#per-content-type-coercion). [#745](https://github.com/metosin/reitit/issues/745).
|
||||||
* **BREAKING** Remove unused `reitit.dependency` ns. [#763](https://github.com/metosin/reitit/pull/763)
|
* **BREAKING** Remove unused `reitit.dependency` ns. [#763](https://github.com/metosin/reitit/pull/763)
|
||||||
|
* Support passing options to malli humanize. See [docs](./doc/coercion/malli_coercion.md). [#467](https://github.com/metosin/reitit/issues/467)
|
||||||
|
|
||||||
## 0.9.2 (2025-10-28)
|
## 0.9.2 (2025-10-28)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -96,3 +96,29 @@ Using `create` with options to create the coercion instead of `coercion`:
|
||||||
;; malli options
|
;; malli options
|
||||||
:options nil})
|
:options nil})
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Configuring humanize error messages
|
||||||
|
|
||||||
|
Malli humanized error messages can be configured using `:options :errors`:
|
||||||
|
|
||||||
|
```clj
|
||||||
|
(reitit.coercion.malli/create
|
||||||
|
{:options
|
||||||
|
{:errors (assoc malli.error/default-errors
|
||||||
|
:malli.core/missing-key {:error/message {:en "MISSING"}})}})
|
||||||
|
```
|
||||||
|
|
||||||
|
See the malli docs for more info.
|
||||||
|
|
||||||
|
## Custom registry
|
||||||
|
|
||||||
|
Malli registry can be configured conveniently via `:options :registry`:
|
||||||
|
|
||||||
|
```clj
|
||||||
|
(require '[malli.core :as m])
|
||||||
|
|
||||||
|
(reitit.coercion.malli/create
|
||||||
|
{:options
|
||||||
|
{:registry {:registry (merge (m/default-schemas)
|
||||||
|
{:my-type :string})}}})
|
||||||
|
```
|
||||||
|
|
|
||||||
|
|
@ -188,7 +188,8 @@
|
||||||
(-open-model [_ schema] schema)
|
(-open-model [_ schema] schema)
|
||||||
(-encode-error [_ error]
|
(-encode-error [_ error]
|
||||||
(cond-> error
|
(cond-> error
|
||||||
(show? :humanized) (assoc :humanized (me/humanize error {:wrap :message}))
|
(show? :humanized) (assoc :humanized (me/humanize error (cond-> {:wrap :message}
|
||||||
|
options (merge options))))
|
||||||
(show? :schema) (update :schema edn/write-string opts)
|
(show? :schema) (update :schema edn/write-string opts)
|
||||||
(show? :errors) (-> (me/with-error-messages opts)
|
(show? :errors) (-> (me/with-error-messages opts)
|
||||||
(update :errors (partial map #(update % :schema edn/write-string opts))))
|
(update :errors (partial map #(update % :schema edn/write-string opts))))
|
||||||
|
|
|
||||||
|
|
@ -122,6 +122,8 @@
|
||||||
(= (count model) 1) (first model)
|
(= (count model) 1) (first model)
|
||||||
;; here be dragons, best effort
|
;; here be dragons, best effort
|
||||||
(every? map? model) (apply mm/meta-merge model)
|
(every? map? model) (apply mm/meta-merge model)
|
||||||
|
;; all elements are the same
|
||||||
|
(apply = model) (first model)
|
||||||
;; fail fast
|
;; fail fast
|
||||||
:else (ex/fail! ::model-error {:message "Can't merge nested clojure specs", :spec model}))
|
:else (ex/fail! ::model-error {:message "Can't merge nested clojure specs", :spec model}))
|
||||||
name))
|
name))
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,7 @@
|
||||||
[metosin/reitit-sieppari "0.9.2"]
|
[metosin/reitit-sieppari "0.9.2"]
|
||||||
[metosin/reitit-pedestal "0.9.2"]
|
[metosin/reitit-pedestal "0.9.2"]
|
||||||
[metosin/ring-swagger-ui "5.20.0"]
|
[metosin/ring-swagger-ui "5.20.0"]
|
||||||
[metosin/spec-tools "0.10.7"]
|
[metosin/spec-tools "0.10.8"]
|
||||||
[metosin/schema-tools "0.13.1"]
|
[metosin/schema-tools "0.13.1"]
|
||||||
[metosin/muuntaja "0.6.11"]
|
[metosin/muuntaja "0.6.11"]
|
||||||
[metosin/jsonista "0.3.13"]
|
[metosin/jsonista "0.3.13"]
|
||||||
|
|
@ -95,7 +95,7 @@
|
||||||
|
|
||||||
;; modules dependencies
|
;; modules dependencies
|
||||||
[metosin/schema-tools "0.13.1"]
|
[metosin/schema-tools "0.13.1"]
|
||||||
[metosin/spec-tools "0.10.7"]
|
[metosin/spec-tools "0.10.8"]
|
||||||
[metosin/muuntaja "0.6.11"]
|
[metosin/muuntaja "0.6.11"]
|
||||||
[metosin/sieppari "0.0.0-alpha13"]
|
[metosin/sieppari "0.0.0-alpha13"]
|
||||||
[metosin/jsonista "0.3.13"]
|
[metosin/jsonista "0.3.13"]
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@
|
||||||
[reitit.swagger-ui :as swagger-ui]
|
[reitit.swagger-ui :as swagger-ui]
|
||||||
[schema.core :as s]
|
[schema.core :as s]
|
||||||
[schema-tools.core]
|
[schema-tools.core]
|
||||||
|
[clojure.spec.alpha :as sp]
|
||||||
[spec-tools.core :as st]
|
[spec-tools.core :as st]
|
||||||
[spec-tools.data-spec :as ds]))
|
[spec-tools.data-spec :as ds]))
|
||||||
|
|
||||||
|
|
@ -1027,3 +1028,36 @@
|
||||||
"reitit.openapi-test.Y" {:type "integer"}}}}
|
"reitit.openapi-test.Y" {:type "integer"}}}}
|
||||||
spec))
|
spec))
|
||||||
(is (nil? (validate spec))))))
|
(is (nil? (validate spec))))))
|
||||||
|
|
||||||
|
(sp/def ::address string?)
|
||||||
|
(sp/def ::zip int?)
|
||||||
|
(sp/def ::city string?)
|
||||||
|
(sp/def ::street string?)
|
||||||
|
(sp/def ::or-and-schema (sp/keys :req-un [(or (and ::address ::zip) (and ::city ::street))]))
|
||||||
|
|
||||||
|
(deftest openapi-spec-tests
|
||||||
|
(testing "s/keys + or maps to :anyOf"
|
||||||
|
(let [app (ring/ring-handler
|
||||||
|
(ring/router
|
||||||
|
[["/openapi.json"
|
||||||
|
{:get {:no-doc true
|
||||||
|
:openapi {:info {:title "" :version "0.0.1"}}
|
||||||
|
:handler (openapi/create-openapi-handler)}}]
|
||||||
|
|
||||||
|
["/spec" {:coercion spec/coercion
|
||||||
|
:post {:summary "or-and-schema"
|
||||||
|
:request {:content {"application/json" {:schema ::or-and-schema}}}
|
||||||
|
:handler identity}}]]
|
||||||
|
{:validate reitit.ring.spec/validate
|
||||||
|
:data {:middleware [openapi/openapi-feature]}}))
|
||||||
|
spec (:body (app {:request-method :get :uri "/openapi.json"}))]
|
||||||
|
(is (nil? (validate spec)))
|
||||||
|
(is (= {:title "reitit.openapi-test/or-and-schema"
|
||||||
|
:type "object"
|
||||||
|
:properties {"address" {:type "string"}
|
||||||
|
"zip" {:type "integer" :format "int64"}
|
||||||
|
"city" {:type "string"}
|
||||||
|
"street" {:type "string"}}
|
||||||
|
:anyOf [{:required ["address" "zip"]}
|
||||||
|
{:required ["city" "street"]}]}
|
||||||
|
(get-in spec [:paths "/spec" :post :requestBody :content "application/json" :schema]))))))
|
||||||
|
|
|
||||||
|
|
@ -583,7 +583,40 @@
|
||||||
:request-method :get}))]
|
:request-method :get}))]
|
||||||
|
|
||||||
(is (= {:status 200, :body {:total "FOO: this, BAR: that"}} (call m/schema custom-meta-merge-checking-schema)))
|
(is (= {:status 200, :body {:total "FOO: this, BAR: that"}} (call m/schema custom-meta-merge-checking-schema)))
|
||||||
(is (= {:status 200, :body {:total "FOO: this, BAR: that"}} (call identity custom-meta-merge-checking-parameters)))))))
|
(is (= {:status 200, :body {:total "FOO: this, BAR: that"}} (call identity custom-meta-merge-checking-parameters)))))
|
||||||
|
|
||||||
|
(testing "malli options"
|
||||||
|
(let [->app (fn [options]
|
||||||
|
(ring/ring-handler
|
||||||
|
(ring/router
|
||||||
|
["/api" {:get {:parameters {:body [:map
|
||||||
|
[:i :int]
|
||||||
|
[:x :string]]}
|
||||||
|
:handler (fn [{{:keys [body]} :parameters}]
|
||||||
|
{:status 200 :body body})}}]
|
||||||
|
{:data {:middleware [rrc/coerce-exceptions-middleware
|
||||||
|
rrc/coerce-request-middleware
|
||||||
|
rrc/coerce-response-middleware]
|
||||||
|
:coercion (malli/create options)}})))
|
||||||
|
request {:uri "/api"
|
||||||
|
:request-method :get
|
||||||
|
:muuntaja/request {:format "application/json"}}]
|
||||||
|
(testing "humanize options"
|
||||||
|
(is (= {:i ["should be an integer"] :x ["missing required key"]}
|
||||||
|
(-> ((->app nil) (assoc request :body-params {:i "x"}))
|
||||||
|
:body
|
||||||
|
:humanized)))
|
||||||
|
(is (= {:i ["SHOULD INT"] :x ["MISSING"]}
|
||||||
|
(-> ((->app {:options {:errors {:int {:error/message {:en "SHOULD INT"}}
|
||||||
|
:malli.core/missing-key {:error/message {:en "MISSING"}}}}})
|
||||||
|
(assoc request :body-params {:i "x"}))
|
||||||
|
:body
|
||||||
|
:humanized))))
|
||||||
|
(testing "overriding registry"
|
||||||
|
(is (= {:body {:i "x" :x "x"} :status 200}
|
||||||
|
(-> ((->app {:options {:registry (merge (m/default-schemas)
|
||||||
|
{:int :string})}})
|
||||||
|
(assoc request :body-params {:i "x" :x "x"}))))))))))
|
||||||
|
|
||||||
#?(:clj
|
#?(:clj
|
||||||
(deftest per-content-type-test
|
(deftest per-content-type-test
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue