From 7352358662af9b6b93f00d66bf563115baaa1fd6 Mon Sep 17 00:00:00 2001 From: Joel Kaasinen Date: Fri, 8 Sep 2023 15:13:27 +0300 Subject: [PATCH] feat: rename openapi :content-types keyword, split for req & resp --- doc/ring/openapi.md | 4 ++-- examples/openapi/src/example/server.clj | 2 +- modules/reitit-openapi/src/reitit/openapi.cljc | 17 ++++++++++------- test/cljc/reitit/openapi_test.clj | 8 +++++--- 4 files changed, 18 insertions(+), 13 deletions(-) diff --git a/doc/ring/openapi.md b/doc/ring/openapi.md index 32f88643..18fb981e 100644 --- a/doc/ring/openapi.md +++ b/doc/ring/openapi.md @@ -19,7 +19,8 @@ The following route data keys contribute to the generated swagger specification: | key | description | | ---------------|-------------| | :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 | :tags | optional set of string or keyword tags for an endpoint api docs | :summary | optional short string summary of an endpoint @@ -90,7 +91,6 @@ openapi example](../../examples/openapi). ```clj ["/pizza" {: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" :schema [:map [:color :keyword] diff --git a/examples/openapi/src/example/server.clj b/examples/openapi/src/example/server.clj index 71233481..57223f1d 100644 --- a/examples/openapi/src/example/server.clj +++ b/examples/openapi/src/example/server.clj @@ -63,7 +63,7 @@ :examples {:purple {:value (pr-str {:color :purple :pineapple false})}}}}} ;; 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" :schema [:map [:success :boolean]] :example {:success true}}}}} diff --git a/modules/reitit-openapi/src/reitit/openapi.cljc b/modules/reitit-openapi/src/reitit/openapi.cljc index bd66ac52..cf4047b0 100644 --- a/modules/reitit-openapi/src/reitit/openapi.cljc +++ b/modules/reitit-openapi/src/reitit/openapi.cljc @@ -12,10 +12,10 @@ (s/def ::tags (s/coll-of (s/or :keyword keyword? :string string?))) (s/def ::summary 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 ::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 "Stability: alpha @@ -31,7 +31,8 @@ | key | description | | ---------------|-------------| | :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 | :tags | optional set of string or keyword tags for an endpoint api docs | :summary | optional short string summary of an endpoint @@ -74,7 +75,9 @@ (-> path (trie/normalize opts) (str/replace #"\{\*" "{"))) (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 parameters (dissoc parameters :request :body :multipart) ->content (fn [data schema] @@ -105,7 +108,7 @@ :type :schema :content-type content-type})] [content-type {:schema schema}]))) - content-types)}}) + request-content-types)}}) (when request ;; request allow to different :requestBody per content-type @@ -119,7 +122,7 @@ :type :schema :content-type content-type})] [content-type (->content data schema)]))) - content-types)) + request-content-types)) (into {} (map (fn [[content-type {:keys [schema] :as data}]] (let [schema (->schema-object schema {:in :requestBody @@ -148,7 +151,7 @@ :type :schema :content-type content-type})] [content-type (->content default schema)]))) - content-types)) + response-content-types)) (when content (into {} (map (fn [[content-type {:keys [schema] :as data}]] diff --git a/test/cljc/reitit/openapi_test.clj b/test/cljc/reitit/openapi_test.clj index bb915917..c950e1c1 100644 --- a/test/cljc/reitit/openapi_test.clj +++ b/test/cljc/reitit/openapi_test.clj @@ -471,7 +471,8 @@ (ring/router [["/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 :request {:content {"application/json" {:schema (->schema :b) :examples {"named-example" {:description "a named example" @@ -696,7 +697,8 @@ [["/parameters" {:post {:description "parameters" :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)}} :body (->schema :default)} :responses {200 {:description "success" @@ -723,7 +725,7 @@ (get-in [:paths "/parameters" :post :requestBody :content]) keys)))) (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 (get-in [:paths "/parameters" :post :responses 200 :content]) keys))))