mirror of
https://github.com/metosin/reitit.git
synced 2025-12-17 00:11:11 +00:00
Merge pull request #676 from metosin/update-validator
update openapi-schema-validator, fix openapi requestBody description
This commit is contained in:
commit
15790f3028
4 changed files with 74 additions and 51 deletions
|
|
@ -125,23 +125,24 @@
|
|||
(when request
|
||||
;; request allow to different :requestBody per content-type
|
||||
{:requestBody
|
||||
{:content (merge
|
||||
(select-keys request [:description])
|
||||
(when-let [{:keys [schema] :as data} (coercion/get-default request)]
|
||||
(into {}
|
||||
(map (fn [content-type]
|
||||
(let [schema (->schema-object schema {:in :requestBody
|
||||
:type :schema
|
||||
:content-type content-type})]
|
||||
[content-type (->content data schema)])))
|
||||
request-content-types))
|
||||
(into {}
|
||||
(map (fn [[content-type {:keys [schema] :as data}]]
|
||||
(let [schema (->schema-object schema {:in :requestBody
|
||||
:type :schema
|
||||
:content-type content-type})]
|
||||
[content-type (->content data schema)])))
|
||||
(dissoc (:content request) :default)))}})
|
||||
(merge
|
||||
(select-keys request [:description])
|
||||
{:content (merge
|
||||
(when-let [{:keys [schema] :as data} (coercion/get-default request)]
|
||||
(into {}
|
||||
(map (fn [content-type]
|
||||
(let [schema (->schema-object schema {:in :requestBody
|
||||
:type :schema
|
||||
:content-type content-type})]
|
||||
[content-type (->content data schema)])))
|
||||
request-content-types))
|
||||
(into {}
|
||||
(map (fn [[content-type {:keys [schema] :as data}]]
|
||||
(let [schema (->schema-object schema {:in :requestBody
|
||||
:type :schema
|
||||
:content-type content-type})]
|
||||
[content-type (->content data schema)])))
|
||||
(dissoc (:content request) :default)))})})
|
||||
(when multipart
|
||||
{:requestBody
|
||||
{:content
|
||||
|
|
|
|||
23
package-lock.json
generated
23
package-lock.json
generated
|
|
@ -6,7 +6,7 @@
|
|||
"": {
|
||||
"name": "reitit",
|
||||
"devDependencies": {
|
||||
"@seriousme/openapi-schema-validator": "^2.1.0",
|
||||
"@seriousme/openapi-schema-validator": "^2.2.1",
|
||||
"karma": "^4.1.0",
|
||||
"karma-chrome-launcher": "^2.2.0",
|
||||
"karma-cli": "^2.0.0",
|
||||
|
|
@ -15,20 +15,31 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@seriousme/openapi-schema-validator": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@seriousme/openapi-schema-validator/-/openapi-schema-validator-2.1.0.tgz",
|
||||
"integrity": "sha512-J461zq7Qj4N/SQlUiyXFelGqtKJenW9DnTjX5fraLk9Lmybq7B6goBieAlMf3D2W+grrVz/hSDodB0faoD9y2Q==",
|
||||
"version": "2.2.1",
|
||||
"resolved": "https://registry.npmjs.org/@seriousme/openapi-schema-validator/-/openapi-schema-validator-2.2.1.tgz",
|
||||
"integrity": "sha512-I+6l2vZ4qx+RyUo8GNnIbeqbv5ao1enSdNFPJ7x3slIVLU8aSBf228qpo+6iNWbRMK4ktF91jsv5KN7PpaJQtg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"ajv": "^8.11.0",
|
||||
"ajv": "^8.12.0",
|
||||
"ajv-draft-04": "^1.0.0",
|
||||
"ajv-formats": "^2.1.1",
|
||||
"js-yaml": "^4.1.0"
|
||||
"js-yaml": "^4.1.0",
|
||||
"minimist": "^1.2.8"
|
||||
},
|
||||
"bin": {
|
||||
"bundle-api": "bin/bundle-api-cli.js",
|
||||
"validate-api": "bin/validate-api-cli.js"
|
||||
}
|
||||
},
|
||||
"node_modules/@seriousme/openapi-schema-validator/node_modules/minimist": {
|
||||
"version": "1.2.8",
|
||||
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
|
||||
"integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==",
|
||||
"dev": true,
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/accepts": {
|
||||
"version": "1.3.7",
|
||||
"resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz",
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
"name": "reitit",
|
||||
"private": true,
|
||||
"devDependencies": {
|
||||
"@seriousme/openapi-schema-validator": "^2.1.0",
|
||||
"@seriousme/openapi-schema-validator": "^2.2.1",
|
||||
"karma": "^4.1.0",
|
||||
"karma-chrome-launcher": "^2.2.0",
|
||||
"karma-cli": "^2.0.0",
|
||||
|
|
|
|||
|
|
@ -869,19 +869,20 @@
|
|||
(ring/router
|
||||
[["/openapi.json"
|
||||
{:get {:no-doc true
|
||||
:openapi {:info {:title "" :version "0.0.1"}}
|
||||
:handler (openapi/create-openapi-handler)}}]
|
||||
|
||||
["/malli" {:coercion malli/coercion}
|
||||
["/plus" {:post {:summary "plus with body"
|
||||
:request {:description "body description"
|
||||
:content {"application/json" {:schema {:x int?, :y int?}
|
||||
:examples {"1+1" {:x 1, :y 1}
|
||||
"1+2" {:x 1, :y 2}}
|
||||
:examples {"1+1" {:value {:x 1, :y 1}}
|
||||
"1+2" {:value {:x 1, :y 2}}}
|
||||
:openapi {:example {:x 2, :y 2}}}}}
|
||||
:responses {200 {:description "success"
|
||||
:content {"application/json" {:schema {:total int?}
|
||||
:examples {"2" {:total 2}
|
||||
"3" {:total 3}}
|
||||
:examples {"2" {:value {:total 2}}
|
||||
"3" {:value {:total 3}}}
|
||||
:openapi {:example {:total 4}}}}}}
|
||||
:handler (fn [request]
|
||||
(let [{:keys [x y]} (-> request :parameters :body)]
|
||||
|
|
@ -891,49 +892,51 @@
|
|||
:data {:middleware [openapi/openapi-feature
|
||||
rrc/coerce-exceptions-middleware
|
||||
rrc/coerce-request-middleware
|
||||
rrc/coerce-response-middleware]}}))]
|
||||
(is (= {"/malli/plus" {:post {:requestBody {:content {:description "body description",
|
||||
"application/json" {:schema {:type "object",
|
||||
rrc/coerce-response-middleware]}}))
|
||||
spec (:body (app {:request-method :get :uri "/openapi.json"}))]
|
||||
(is (= {"/malli/plus" {:post {:requestBody {:description "body description",
|
||||
:content {"application/json" {:schema {:type "object",
|
||||
:properties {:x {:type "integer"},
|
||||
:y {:type "integer"}},
|
||||
:required [:x :y],
|
||||
:additionalProperties false},
|
||||
:examples {"1+1" {:x 1, :y 1}, "1+2" {:x 1, :y 2}},
|
||||
:examples {"1+1" {:value {:x 1, :y 1}}
|
||||
"1+2" {:value {:x 1, :y 2}}},
|
||||
:example {:x 2, :y 2}}}},
|
||||
:responses {200 {:description "success",
|
||||
:content {"application/json" {:schema {:type "object",
|
||||
:properties {:total {:type "integer"}},
|
||||
:required [:total],
|
||||
:additionalProperties false},
|
||||
:examples {"2" {:total 2}, "3" {:total 3}},
|
||||
:examples {"2" {:value {:total 2}},
|
||||
"3" {:value {:total 3}}},
|
||||
:example {:total 4}}}}},
|
||||
:summary "plus with body"}}}
|
||||
(-> {:request-method :get
|
||||
:uri "/openapi.json"}
|
||||
(app)
|
||||
:body
|
||||
:paths))))
|
||||
(:paths spec)))
|
||||
(is (nil? (validate spec))))
|
||||
(testing "ref schemas"
|
||||
(let [registry (merge (mc/base-schemas)
|
||||
(mc/type-schemas)
|
||||
{::plus [:map [:x :int] [:y ::y]]
|
||||
::y :int})
|
||||
{"plus" [:map [:x :int] [:y "y"]]
|
||||
"y" :int})
|
||||
app (ring/ring-handler
|
||||
(ring/router
|
||||
[["/openapi.json"
|
||||
{:get {:no-doc true
|
||||
:openapi {:info {:title "" :version "0.0.1"}}
|
||||
:handler (openapi/create-openapi-handler)}}]
|
||||
["/post"
|
||||
{:post {:coercion malli/coercion
|
||||
:parameters {:body (mc/schema ::plus {:registry registry})}
|
||||
:parameters {:body (mc/schema "plus" {:registry registry})}
|
||||
:handler identity}}]
|
||||
["/get"
|
||||
{:get {:coercion malli/coercion
|
||||
:parameters {:query (mc/schema ::plus {:registry registry})}
|
||||
:parameters {:query (mc/schema "plus" {:registry registry})}
|
||||
:handler identity}}]]))
|
||||
spec (:body (app {:request-method :get :uri "/openapi.json"}))]
|
||||
(is (= {:openapi "3.1.0"
|
||||
:x-id #{:reitit.openapi/default}
|
||||
:info {:title "" :version "0.0.1"}
|
||||
:paths {"/get" {:get {:parameters [{:in "query"
|
||||
:name :x
|
||||
:required true
|
||||
|
|
@ -941,25 +944,27 @@
|
|||
{:in "query"
|
||||
:name :y
|
||||
:required true
|
||||
:schema {:$ref "#/components/schemas/reitit.openapi-test~1y"}}]}}
|
||||
:schema {:$ref "#/components/schemas/y"}}]}}
|
||||
"/post" {:post
|
||||
{:requestBody
|
||||
{:content
|
||||
{"application/json"
|
||||
{:schema
|
||||
{:$ref "#/components/schemas/reitit.openapi-test~1plus"}}}}}}}
|
||||
{:$ref "#/components/schemas/plus"}}}}}}}
|
||||
:components {:schemas
|
||||
{"reitit.openapi-test/y" {:type "integer"}
|
||||
"reitit.openapi-test/plus" {:type "object"
|
||||
:properties {:x {:type "integer"}
|
||||
:y {:$ref "#/components/schemas/reitit.openapi-test~1y"}}
|
||||
:required [:x :y]}}}}
|
||||
spec))))
|
||||
{"y" {:type "integer"}
|
||||
"plus" {:type "object"
|
||||
:properties {:x {:type "integer"}
|
||||
:y {:$ref "#/components/schemas/y"}}
|
||||
:required [:x :y]}}}}
|
||||
spec))
|
||||
(is (nil? (validate spec)))))
|
||||
(testing "var schemas"
|
||||
(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)}}]
|
||||
["/post"
|
||||
{:post {:coercion malli/coercion
|
||||
|
|
@ -972,6 +977,7 @@
|
|||
spec (:body (app {:request-method :get :uri "/openapi.json"}))]
|
||||
(is (= {:openapi "3.1.0"
|
||||
:x-id #{:reitit.openapi/default}
|
||||
:info {:title "" :version "0.0.1"}
|
||||
:paths
|
||||
{"/post"
|
||||
{:post
|
||||
|
|
@ -999,4 +1005,9 @@
|
|||
:y {:$ref "#/components/schemas/reitit.openapi-test~1Y"}}
|
||||
:required [:x :y]}
|
||||
"reitit.openapi-test/Y" {:type "integer"}}}}
|
||||
spec)))))
|
||||
spec))
|
||||
;; TODO: the OAS 3.1 json schema disallows "/" in :components :schemas keys,
|
||||
;; even though the text of the spec allows it. See:
|
||||
;; https://github.com/seriousme/openapi-schema-validator/blob/772375bf4895f0e641d103c27140cdd1d2afc34e/schemas/v3.1/schema.json#L282
|
||||
#_
|
||||
(is (nil? (validate spec))))))
|
||||
|
|
|
|||
Loading…
Reference in a new issue