feat: rename openapi :content-types keyword, split for req & resp

This commit is contained in:
Joel Kaasinen 2023-09-08 15:13:27 +03:00
parent 5d0bce1242
commit 7352358662
4 changed files with 18 additions and 13 deletions

View file

@ -19,7 +19,8 @@ The following route data keys contribute to the generated swagger specification:
| key | description | | key | description |
| ---------------|-------------| | ---------------|-------------|
| :openapi | map of any openapi data. Can contain keys like `:deprecated`. | :openapi | map of any openapi data. Can contain keys like `:deprecated`.
| :content-types | vector of supported content types. Defaults to `["application/json"]` | :openapi/request-content-types | vector of supported request content types. Defaults to `["application/json"]`. Only needed if you use the [:request :content :default] coercion.
| :openapi/response-content-types | vector of supported response content types. Defaults to `["application/json"]`. Only needed if you use the [:response nnn :content :default] coercion.
| :no-doc | optional boolean to exclude endpoint from api docs | :no-doc | optional boolean to exclude endpoint from api docs
| :tags | optional set of string or keyword tags for an endpoint api docs | :tags | optional set of string or keyword tags for an endpoint api docs
| :summary | optional short string summary of an endpoint | :summary | optional short string summary of an endpoint
@ -90,7 +91,6 @@ openapi example](../../examples/openapi).
```clj ```clj
["/pizza" ["/pizza"
{:get {:summary "Fetch a pizza | Multiple content-types, multiple examples" {:get {:summary "Fetch a pizza | Multiple content-types, multiple examples"
:content-types ["application/json" "application/edn"]
:responses {200 {:content {"application/json" {:description "Fetch a pizza as json" :responses {200 {:content {"application/json" {:description "Fetch a pizza as json"
:schema [:map :schema [:map
[:color :keyword] [:color :keyword]

View file

@ -63,7 +63,7 @@
:examples {:purple {:value (pr-str {:color :purple :examples {:purple {:value (pr-str {:color :purple
:pineapple false})}}}}} :pineapple false})}}}}}
;; Need to list content types explicitly because we use :default in :responses ;; Need to list content types explicitly because we use :default in :responses
:content-types ["application/json" "application/edn"] :openapi/response-content-types ["application/json" "application/edn"]
:responses {200 {:content {:default {:description "Success" :responses {200 {:content {:default {:description "Success"
:schema [:map [:success :boolean]] :schema [:map [:success :boolean]]
:example {:success true}}}}} :example {:success true}}}}}

View file

@ -12,10 +12,10 @@
(s/def ::tags (s/coll-of (s/or :keyword keyword? :string string?))) (s/def ::tags (s/coll-of (s/or :keyword keyword? :string string?)))
(s/def ::summary string?) (s/def ::summary string?)
(s/def ::description string?) (s/def ::description string?)
(s/def ::content-types (s/coll-of string?)) (s/def :openapi/content-types (s/coll-of string?))
(s/def ::openapi (s/keys :opt-un [::id])) (s/def ::openapi (s/keys :opt-un [::id]))
(s/def ::spec (s/keys :opt-un [::openapi ::no-doc ::tags ::summary ::description ::content-types])) (s/def ::spec (s/keys :opt-un [::openapi ::no-doc ::tags ::summary ::description] :opt [:openapi/content-types]))
(def openapi-feature (def openapi-feature
"Stability: alpha "Stability: alpha
@ -31,7 +31,8 @@
| key | description | | key | description |
| ---------------|-------------| | ---------------|-------------|
| :openapi | map of any openapi-data. Can contain keys like `:deprecated`. | :openapi | map of any openapi-data. Can contain keys like `:deprecated`.
| :content-types | vector of supported content types. Defaults to `[\"application/json\"]` | :openapi/request-content-types | vector of supported request content types. Defaults to `[\"application/json\"]` :response nnn :content :default. Only needed if you use the [:request :content :default] coercion.
| :openapi/response-content-types | vector of supported response content types. Defaults to `[\"application/json\"]`. Only needed if you use the [:response nnn :content :default] coercion.
| :no-doc | optional boolean to exclude endpoint from api docs | :no-doc | optional boolean to exclude endpoint from api docs
| :tags | optional set of string or keyword tags for an endpoint api docs | :tags | optional set of string or keyword tags for an endpoint api docs
| :summary | optional short string summary of an endpoint | :summary | optional short string summary of an endpoint
@ -74,7 +75,9 @@
(-> path (trie/normalize opts) (str/replace #"\{\*" "{"))) (-> path (trie/normalize opts) (str/replace #"\{\*" "{")))
(defn -get-apidocs-openapi (defn -get-apidocs-openapi
[coercion {:keys [request parameters responses content-types] :or {content-types ["application/json"]}}] [coercion {:keys [request parameters responses openapi/request-content-types openapi/response-content-types]
:or {request-content-types ["application/json"]
response-content-types ["application/json"]}}]
(let [{:keys [body multipart]} parameters (let [{:keys [body multipart]} parameters
parameters (dissoc parameters :request :body :multipart) parameters (dissoc parameters :request :body :multipart)
->content (fn [data schema] ->content (fn [data schema]
@ -105,7 +108,7 @@
:type :schema :type :schema
:content-type content-type})] :content-type content-type})]
[content-type {:schema schema}]))) [content-type {:schema schema}])))
content-types)}}) request-content-types)}})
(when request (when request
;; request allow to different :requestBody per content-type ;; request allow to different :requestBody per content-type
@ -119,7 +122,7 @@
:type :schema :type :schema
:content-type content-type})] :content-type content-type})]
[content-type (->content data schema)]))) [content-type (->content data schema)])))
content-types)) request-content-types))
(into {} (into {}
(map (fn [[content-type {:keys [schema] :as data}]] (map (fn [[content-type {:keys [schema] :as data}]]
(let [schema (->schema-object schema {:in :requestBody (let [schema (->schema-object schema {:in :requestBody
@ -148,7 +151,7 @@
:type :schema :type :schema
:content-type content-type})] :content-type content-type})]
[content-type (->content default schema)]))) [content-type (->content default schema)])))
content-types)) response-content-types))
(when content (when content
(into {} (into {}
(map (fn [[content-type {:keys [schema] :as data}]] (map (fn [[content-type {:keys [schema] :as data}]]

View file

@ -471,7 +471,8 @@
(ring/router (ring/router
[["/examples" [["/examples"
{:post {:decription "examples" {:post {:decription "examples"
:content-types ["application/json" "application/edn"] :openapi/request-content-types ["application/json" "application/edn"]
:openapi/response-content-types ["application/json" "application/edn"]
:coercion @coercion :coercion @coercion
:request {:content {"application/json" {:schema (->schema :b) :request {:content {"application/json" {:schema (->schema :b)
:examples {"named-example" {:description "a named example" :examples {"named-example" {:description "a named example"
@ -696,7 +697,8 @@
[["/parameters" [["/parameters"
{:post {:description "parameters" {:post {:description "parameters"
:coercion coercion :coercion coercion
:content-types [content-type] ;; TODO should this be under :openapi ? :openapi/request-content-types [content-type]
:openapi/response-content-types [content-type "application/response"]
:request {:content {"application/transit" {:schema (->schema :transit)}} :request {:content {"application/transit" {:schema (->schema :transit)}}
:body (->schema :default)} :body (->schema :default)}
:responses {200 {:description "success" :responses {200 {:description "success"
@ -723,7 +725,7 @@
(get-in [:paths "/parameters" :post :requestBody :content]) (get-in [:paths "/parameters" :post :requestBody :content])
keys)))) keys))))
(testing "body response" (testing "body response"
(is (match? (matchers/in-any-order [content-type "application/transit"]) (is (match? (matchers/in-any-order [content-type "application/transit" "application/response"])
(-> spec (-> spec
(get-in [:paths "/parameters" :post :responses 200 :content]) (get-in [:paths "/parameters" :post :responses 200 :content])
keys)))) keys))))