mirror of
https://github.com/metosin/reitit.git
synced 2025-12-17 00:11:11 +00:00
top-level :request coercion & stuff
This commit is contained in:
parent
93a4246682
commit
b1404ada6d
11 changed files with 180 additions and 144 deletions
|
|
@ -157,21 +157,21 @@ You can also specify request and response body schemas per content-type. The syn
|
|||
```clj
|
||||
(def app
|
||||
(ring/ring-handler
|
||||
(ring/router
|
||||
["/api"
|
||||
["/example" {:post {:coercion reitit.coercion.schema/coercion
|
||||
:parameters {:request {:content {"application/json" {:y s/Int}
|
||||
"application/edn" {:z s/Int}}
|
||||
;; default if no content-type matches:
|
||||
:body {:yy s/Int}}}
|
||||
:responses {200 {:content {"application/json" {:w s/Int}
|
||||
"application/edn" {:x s/Int}}
|
||||
;; default if no content-type matches:
|
||||
:body {:ww s/Int}}
|
||||
:handler ...}}]]
|
||||
{:data {:middleware [rrc/coerce-exceptions-middleware
|
||||
rrc/coerce-request-middleware
|
||||
rrc/coerce-response-middleware]}})))
|
||||
(ring/router
|
||||
["/api"
|
||||
["/example" {:post {:coercion reitit.coercion.schema/coercion
|
||||
:request {:content {"application/json" {:y s/Int}
|
||||
"application/edn" {:z s/Int}}
|
||||
;; default if no content-type matches:
|
||||
:body {:yy s/Int}}
|
||||
:responses {200 {:content {"application/json" {:w s/Int}
|
||||
"application/edn" {:x s/Int}}
|
||||
;; default if no content-type matches:
|
||||
:body {:ww s/Int}}
|
||||
:handler ...}}}]]
|
||||
{:data {:middleware [rrc/coerce-exceptions-middleware
|
||||
rrc/coerce-request-middleware
|
||||
rrc/coerce-response-middleware]}})))
|
||||
```
|
||||
|
||||
## Pretty printing spec errors
|
||||
|
|
|
|||
|
|
@ -37,7 +37,6 @@
|
|||
(def ^:no-doc default-parameter-coercion
|
||||
{:query (->ParameterCoercion :query-params :string true true)
|
||||
:body (->ParameterCoercion :body-params :body false false)
|
||||
:request (->ParameterCoercion :body-params :request false false)
|
||||
:form (->ParameterCoercion :form-params :string true true)
|
||||
:header (->ParameterCoercion :headers :string true true)
|
||||
:path (->ParameterCoercion :path-params :string true true)
|
||||
|
|
@ -83,34 +82,45 @@
|
|||
value)
|
||||
|
||||
;; TODO: support faster key walking, walk/keywordize-keys is quite slow...
|
||||
(defn request-coercer [coercion type model {::keys [extract-request-format parameter-coercion serialize-failed-result]
|
||||
(defn request-coercer [coercion type model {::keys [extract-request-format parameter-coercion serialize-failed-result skip]
|
||||
:or {extract-request-format extract-request-format-default
|
||||
parameter-coercion default-parameter-coercion}}]
|
||||
parameter-coercion default-parameter-coercion
|
||||
skip #{}}}]
|
||||
(if coercion
|
||||
(if-let [{:keys [keywordize? open? in style]} (parameter-coercion type)]
|
||||
(let [transform (comp (if keywordize? walk/keywordize-keys identity) in)
|
||||
->open (if open? #(-open-model coercion %) identity)
|
||||
format-schema-pairs (if (= :request style)
|
||||
(conj (:content model) [:default {:schema (:body model)}])
|
||||
[[:default {:schema model}]])
|
||||
format->coercer (some->> (for [[format {:keys [schema]}] format-schema-pairs
|
||||
:when schema
|
||||
:let [type (case style :request :body style)]]
|
||||
[format (-request-coercer coercion type (->open schema))])
|
||||
(filter second)
|
||||
(seq)
|
||||
(into {}))]
|
||||
(when format->coercer
|
||||
(fn [request]
|
||||
(let [value (transform request)
|
||||
format (extract-request-format request)
|
||||
coercer (or (format->coercer format)
|
||||
(format->coercer :default)
|
||||
-identity-coercer)
|
||||
result (coercer value format)]
|
||||
(if (error? result)
|
||||
(request-coercion-failed! result coercion value in request serialize-failed-result)
|
||||
result))))))))
|
||||
(when-let [{:keys [keywordize? open? in style]} (parameter-coercion type)]
|
||||
(when-not (skip style)
|
||||
(let [transform (comp (if keywordize? walk/keywordize-keys identity) in)
|
||||
->open (if open? #(-open-model coercion %) identity)
|
||||
coercer (-request-coercer coercion style (->open model))]
|
||||
(when coercer
|
||||
(fn [request]
|
||||
(let [value (transform request)
|
||||
format (extract-request-format request)
|
||||
result (coercer value format)]
|
||||
(if (error? result)
|
||||
(request-coercion-failed! result coercion value in request serialize-failed-result)
|
||||
result)))))))))
|
||||
|
||||
(defn content-request-coercer [coercion {:keys [content body]} {::keys [extract-request-format serialize-failed-result]
|
||||
:or {extract-request-format extract-request-format-default}}]
|
||||
(when coercion
|
||||
(let [in :body-params
|
||||
format->coercer (some->> (concat (when body
|
||||
[[:default (-request-coercer coercion :body body)]])
|
||||
(for [[format {:keys [schema]}] content, :when schema]
|
||||
[format (-request-coercer coercion :body schema)]))
|
||||
(filter second) (seq) (into (array-map)))]
|
||||
(when format->coercer
|
||||
(fn [request]
|
||||
(let [value (in request)
|
||||
format (extract-request-format request)
|
||||
coercer (or (format->coercer format)
|
||||
(format->coercer :default)
|
||||
-identity-coercer)
|
||||
result (coercer value format)]
|
||||
(if (error? result)
|
||||
(request-coercion-failed! result coercion value in request serialize-failed-result)
|
||||
result)))))))
|
||||
|
||||
(defn extract-response-format-default [request _]
|
||||
(-> request :muuntaja/response :format))
|
||||
|
|
@ -118,18 +128,18 @@
|
|||
(defn response-coercer [coercion {:keys [content body]} {:keys [extract-response-format serialize-failed-result]
|
||||
:or {extract-response-format extract-response-format-default}}]
|
||||
(if coercion
|
||||
(let [per-format-coercers (some->> (for [[format {:keys [schema]}] content
|
||||
:when schema]
|
||||
[format (-response-coercer coercion schema)])
|
||||
(filter second)
|
||||
(seq)
|
||||
(into {}))
|
||||
default (when body (-response-coercer coercion body))]
|
||||
(when (or per-format-coercers default)
|
||||
(let [format->coercer (some->> (concat (when body
|
||||
[[:default (-response-coercer coercion body)]])
|
||||
(for [[format {:keys [schema]}] content, :when schema]
|
||||
[format (-response-coercer coercion schema)]))
|
||||
(filter second) (seq) (into (array-map)))]
|
||||
(when format->coercer
|
||||
(fn [request response]
|
||||
(let [format (extract-response-format request response)
|
||||
value (:body response)
|
||||
coercer (get per-format-coercers format (or default -identity-coercer))
|
||||
coercer (or (format->coercer format)
|
||||
(format->coercer :default)
|
||||
-identity-coercer)
|
||||
result (coercer value format)]
|
||||
(if (error? result)
|
||||
(response-coercion-failed! result coercion value request response serialize-failed-result)
|
||||
|
|
@ -153,10 +163,15 @@
|
|||
(impl/fast-assoc response :body (coercer request response))
|
||||
response)))
|
||||
|
||||
(defn request-coercers [coercion parameters opts]
|
||||
(some->> (for [[k v] parameters, :when v]
|
||||
[k (request-coercer coercion k v opts)])
|
||||
(filter second) (seq) (into {})))
|
||||
(defn request-coercers
|
||||
([coercion parameters opts]
|
||||
(some->> (for [[k v] parameters, :when v]
|
||||
[k (request-coercer coercion k v opts)])
|
||||
(filter second) (seq) (into {})))
|
||||
([coercion parameters request opts]
|
||||
(let [crc (when request (some->> (content-request-coercer coercion request opts) (array-map :request)))
|
||||
rcs (request-coercers coercion parameters (cond-> opts request (assoc ::skip #{:body})))]
|
||||
(if (and crc rcs) (into crc (vec rcs)) (or crc rcs)))))
|
||||
|
||||
(defn response-coercers [coercion responses opts]
|
||||
(some->> (for [[status model] responses]
|
||||
|
|
@ -170,8 +185,8 @@
|
|||
;; api-docs
|
||||
;;
|
||||
|
||||
(defn -warn-unsupported-coercions [{:keys [parameters responses] :as _data}]
|
||||
(when (:request parameters)
|
||||
(defn -warn-unsupported-coercions [{:keys [request responses] :as _data}]
|
||||
(when request
|
||||
(println "WARNING [reitit.coercion]: swagger apidocs don't support :request coercion"))
|
||||
(when (some :content (vals responses))
|
||||
(println "WARNING [reitit.coercion]: swagger apidocs don't support :responses :content coercion")))
|
||||
|
|
@ -197,7 +212,6 @@
|
|||
(into {}))))
|
||||
(-get-apidocs coercion specification))))))
|
||||
|
||||
|
||||
;;
|
||||
;; integration
|
||||
;;
|
||||
|
|
|
|||
|
|
@ -10,15 +10,15 @@
|
|||
[]
|
||||
{:name ::coerce-request
|
||||
:spec ::rs/parameters
|
||||
:compile (fn [{:keys [coercion parameters]} opts]
|
||||
:compile (fn [{:keys [coercion parameters request]} opts]
|
||||
(cond
|
||||
;; no coercion, skip
|
||||
(not coercion) nil
|
||||
;; just coercion, don't mount
|
||||
(not parameters) {}
|
||||
(not (or parameters request)) {}
|
||||
;; mount
|
||||
:else
|
||||
(if-let [coercers (coercion/request-coercers coercion parameters opts)]
|
||||
(if-let [coercers (coercion/request-coercers coercion parameters request opts)]
|
||||
{:enter (fn [ctx]
|
||||
(let [request (:request ctx)
|
||||
coerced (coercion/coerce-request coercers request)
|
||||
|
|
|
|||
|
|
@ -134,8 +134,8 @@
|
|||
:options nil})
|
||||
|
||||
(defn -get-apidocs-openapi
|
||||
[_ {:keys [parameters responses content-types] :or {content-types ["application/json"]}} options]
|
||||
(let [{:keys [body request multipart]} parameters
|
||||
[_ {:keys [request parameters responses content-types] :or {content-types ["application/json"]}} options]
|
||||
(let [{:keys [body multipart]} parameters
|
||||
parameters (dissoc parameters :request :body :multipart)
|
||||
->schema-object (fn [schema opts]
|
||||
(let [current-opts (merge options opts)]
|
||||
|
|
|
|||
|
|
@ -32,17 +32,23 @@
|
|||
(defn -update-paths [f]
|
||||
(let [not-request? #(not= :request %)
|
||||
http-method? #(contains? http-methods %)]
|
||||
[;; default parameters and responses
|
||||
[;; default parameters
|
||||
[[:parameters not-request?] f]
|
||||
[[http-method? :parameters not-request?] f]
|
||||
|
||||
;; default responses
|
||||
[[:responses any? :body] f]
|
||||
[[http-method? :responses any? :body] f]
|
||||
|
||||
;; openapi3 parameters and responses
|
||||
[[:parameters :request :content any? :schema] f]
|
||||
[[http-method? :parameters :request :content any? :schema] f]
|
||||
[[:parameters :request :body] f]
|
||||
[[http-method? :parameters :request :body] f]
|
||||
;; openapi3 request
|
||||
[[:request :content any? :schema] f]
|
||||
[[http-method? :request :content any? :schema] f]
|
||||
|
||||
;; openapi3 LEGACY body
|
||||
[[:request :body] f]
|
||||
[[http-method? :request :body] f]
|
||||
|
||||
;; openapi3 responses
|
||||
[[:responses any? :content any? :schema] f]
|
||||
[[http-method? :responses any? :content any? :schema] f]]))
|
||||
|
||||
|
|
|
|||
|
|
@ -24,15 +24,15 @@
|
|||
and :parameters from route data, otherwise does not mount."
|
||||
{:name ::coerce-request
|
||||
:spec ::rs/parameters
|
||||
:compile (fn [{:keys [coercion parameters]} opts]
|
||||
:compile (fn [{:keys [coercion parameters request]} opts]
|
||||
(cond
|
||||
;; no coercion, skip
|
||||
(not coercion) nil
|
||||
;; just coercion, don't mount
|
||||
(not parameters) {}
|
||||
(not (or parameters request)) {}
|
||||
;; mount
|
||||
:else
|
||||
(if-let [coercers (coercion/request-coercers coercion parameters opts)]
|
||||
(if-let [coercers (coercion/request-coercers coercion parameters request opts)]
|
||||
(fn [handler]
|
||||
(fn
|
||||
([request]
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@
|
|||
(reify coercion/Coercion
|
||||
(-get-name [_] :schema)
|
||||
(-get-options [_] opts)
|
||||
(-get-apidocs [_ specification {:keys [parameters responses content-types]
|
||||
(-get-apidocs [_ specification {:keys [request parameters responses content-types]
|
||||
:or {content-types ["application/json"]}}]
|
||||
;; TODO: this looks identical to spec, refactor when schema is done.
|
||||
(case specification
|
||||
|
|
@ -67,12 +67,12 @@
|
|||
(when (:body parameters)
|
||||
{:requestBody (openapi/openapi-spec
|
||||
{::openapi/content (zipmap content-types (repeat (:body parameters)))})})
|
||||
(when (:request parameters)
|
||||
(when request
|
||||
{:requestBody (openapi/openapi-spec
|
||||
{::openapi/content (merge
|
||||
(when-let [default (get-in parameters [:request :body])]
|
||||
(when-let [default (:body request)]
|
||||
(zipmap content-types (repeat default)))
|
||||
(->> (for [[content-type {:keys [schema]}] (:content (:request parameters))]
|
||||
(->> (for [[content-type {:keys [schema]}] (:content request)]
|
||||
[content-type schema])
|
||||
(into {})))})})
|
||||
(when (:multipart parameters)
|
||||
|
|
|
|||
|
|
@ -88,7 +88,7 @@
|
|||
(reify coercion/Coercion
|
||||
(-get-name [_] :spec)
|
||||
(-get-options [_] opts)
|
||||
(-get-apidocs [this specification {:keys [parameters responses content-types]
|
||||
(-get-apidocs [this specification {:keys [request parameters responses content-types]
|
||||
:or {content-types ["application/json"]}}]
|
||||
(case specification
|
||||
:swagger (swagger/swagger-spec
|
||||
|
|
@ -108,12 +108,12 @@
|
|||
(when (:body parameters)
|
||||
{:requestBody (openapi/openapi-spec
|
||||
{::openapi/content (zipmap content-types (repeat (:body parameters)))})})
|
||||
(when (:request parameters)
|
||||
(when request
|
||||
{:requestBody (openapi/openapi-spec
|
||||
{::openapi/content (merge
|
||||
(when-let [default (get-in parameters [:request :body])]
|
||||
(when-let [default (:body request)]
|
||||
(zipmap content-types (repeat default)))
|
||||
(->> (for [[content-type {:keys [schema]}] (:content (:request parameters))]
|
||||
(->> (for [[content-type {:keys [schema]}] (:content request)]
|
||||
[content-type schema])
|
||||
(into {})))})})
|
||||
(when (:multipart parameters)
|
||||
|
|
|
|||
|
|
@ -457,8 +457,8 @@
|
|||
[["/examples"
|
||||
{:post {:decription "examples"
|
||||
:coercion @coercion
|
||||
:parameters {:query (->schema :q)
|
||||
:request {:body (->schema :b)}}
|
||||
:request {:body (->schema :b)}
|
||||
:parameters {:query (->schema :q)}
|
||||
:responses {200 {:description "success"
|
||||
:body (->schema :ok)}}
|
||||
:openapi {:requestBody
|
||||
|
|
@ -573,8 +573,8 @@
|
|||
[["/parameters"
|
||||
{:post {:description "parameters"
|
||||
:coercion coercion
|
||||
:parameters {:request {:content {"application/json" {:schema (->schema :b)}
|
||||
"application/edn" {:schema (->schema :c)}}}}
|
||||
:request {:content {"application/json" {:schema (->schema :b)}
|
||||
"application/edn" {:schema (->schema :c)}}}
|
||||
:responses {200 {:description "success"
|
||||
:content {"application/json" {:schema (->schema :ok)}
|
||||
"application/edn" {:schema (->schema :edn)}}}}
|
||||
|
|
@ -664,8 +664,8 @@
|
|||
{:post {:description "parameters"
|
||||
:coercion coercion
|
||||
:content-types [content-type] ;; TODO should this be under :openapi ?
|
||||
:parameters {:request {:content {"application/transit" {:schema (->schema :transit)}}
|
||||
:body (->schema :default)}}
|
||||
:request {:content {"application/transit" {:schema (->schema :transit)}}
|
||||
:body (->schema :default)}
|
||||
:responses {200 {:description "success"
|
||||
:content {"application/transit" {:schema (->schema :transit)}}
|
||||
:body (->schema :default)}}
|
||||
|
|
@ -705,16 +705,15 @@
|
|||
[["/parameters"
|
||||
{:post {:description "parameters"
|
||||
:coercion malli/coercion
|
||||
:parameters {:request
|
||||
{:body
|
||||
[:schema
|
||||
{:registry {"friend" [:map
|
||||
[:age int?]
|
||||
[:pet [:ref "pet"]]]
|
||||
"pet" [:map
|
||||
[:name :string]
|
||||
[:friends [:vector [:ref "friend"]]]]}}
|
||||
"friend"]}}
|
||||
:request {:body
|
||||
[:schema
|
||||
{:registry {"friend" [:map
|
||||
[:age int?]
|
||||
[:pet [:ref "pet"]]]
|
||||
"pet" [:map
|
||||
[:name :string]
|
||||
[:friends [:vector [:ref "friend"]]]]}}
|
||||
"friend"]}
|
||||
:handler (fn [req]
|
||||
{:status 200
|
||||
:body (-> req :parameters :request)})}}]
|
||||
|
|
|
|||
|
|
@ -606,53 +606,70 @@
|
|||
{:request any? :response (clojure.spec.alpha/spec #{:end})}
|
||||
{:request any? :response (clojure.spec.alpha/spec #{:default})}]]]
|
||||
(testing (str coercion)
|
||||
(let [app (ring/ring-handler
|
||||
(ring/router
|
||||
["/foo" {:post {:parameters {:request {:content {"application/json" {:schema json-request}
|
||||
"application/edn" {:schema edn-request}}
|
||||
:body default-request}}
|
||||
:responses {200 {:content {"application/json" {:schema json-response}
|
||||
"application/edn" {:schema edn-response}}
|
||||
:body default-response}}
|
||||
:handler (fn [req]
|
||||
{:status 200
|
||||
:body (-> req :parameters :request)})}}]
|
||||
{:validate reitit.ring.spec/validate
|
||||
:data {:middleware [rrc/coerce-request-middleware
|
||||
rrc/coerce-response-middleware]
|
||||
:coercion coercion}}))
|
||||
call (fn [request]
|
||||
(try
|
||||
(app request)
|
||||
(catch ExceptionInfo e
|
||||
(select-keys (ex-data e) [:type :in]))))
|
||||
request (fn [request-format response-format body]
|
||||
{:request-method :post
|
||||
:uri "/foo"
|
||||
:muuntaja/request {:format request-format}
|
||||
:muuntaja/response {:format response-format}
|
||||
:body-params body})]
|
||||
(testing "succesful call"
|
||||
(is (= {:status 200 :body {:request :json, :response :json}}
|
||||
(call (request "application/json" "application/json" {:request :json :response :json}))))
|
||||
(is (= {:status 200 :body {:request :edn, :response :json}}
|
||||
(call (request "application/edn" "application/json" {:request :edn :response :json}))))
|
||||
(is (= {:status 200 :body {:request :default, :response :default}}
|
||||
(call (request "application/transit" "application/transit" {:request :default :response :default})))))
|
||||
(testing "request validation fails"
|
||||
(is (= {:type :reitit.coercion/request-coercion :in [:request :body-params]}
|
||||
(call (request "application/edn" "application/json" {:request :json :response :json}))))
|
||||
(is (= {:type :reitit.coercion/request-coercion :in [:request :body-params]}
|
||||
(call (request "application/json" "application/json" {:request :edn :response :json}))))
|
||||
(is (= {:type :reitit.coercion/request-coercion :in [:request :body-params]}
|
||||
(call (request "application/transit" "application/json" {:request :edn :response :json})))))
|
||||
(testing "response validation fails"
|
||||
(is (= {:type :reitit.coercion/response-coercion :in [:response :body]}
|
||||
(call (request "application/json" "application/json" {:request :json :response :edn}))))
|
||||
(is (= {:type :reitit.coercion/response-coercion :in [:response :body]}
|
||||
(call (request "application/json" "application/edn" {:request :json :response :json}))))
|
||||
(is (= {:type :reitit.coercion/response-coercion :in [:response :body]}
|
||||
(call (request "application/json" "application/transit" {:request :json :response :json})))))))))
|
||||
(doseq [app [(ring/ring-handler
|
||||
(ring/router
|
||||
["/foo" {:post {:request {:content {"application/json" {:schema json-request}
|
||||
"application/edn" {:schema edn-request}}
|
||||
:body default-request}
|
||||
:responses {200 {:content {"application/json" {:schema json-response}
|
||||
"application/edn" {:schema edn-response}}
|
||||
:body default-response}}
|
||||
:handler (fn [req]
|
||||
{:status 200
|
||||
:body (-> req :parameters :request)})}}]
|
||||
{:validate reitit.ring.spec/validate
|
||||
:data {:middleware [rrc/coerce-request-middleware
|
||||
rrc/coerce-response-middleware]
|
||||
:coercion coercion}}))
|
||||
(ring/ring-handler
|
||||
(ring/router
|
||||
["/foo" {:post {:request {:content {"application/json" {:schema json-request}
|
||||
"application/edn" {:schema edn-request}
|
||||
:default {:schema default-request}}
|
||||
:body json-request} ;; not applied as :default exists
|
||||
:responses {200 {:content {"application/json" {:schema json-response}
|
||||
"application/edn" {:schema edn-response}
|
||||
:default {:schema default-response}}
|
||||
:body json-response}} ;; not applied as :default exists
|
||||
:handler (fn [req]
|
||||
{:status 200
|
||||
:body (-> req :parameters :request)})}}]
|
||||
{:validate reitit.ring.spec/validate
|
||||
:data {:middleware [rrc/coerce-request-middleware
|
||||
rrc/coerce-response-middleware]
|
||||
:coercion coercion}}))]]
|
||||
(let [call (fn [request]
|
||||
(try
|
||||
(app request)
|
||||
(catch ExceptionInfo e
|
||||
(select-keys (ex-data e) [:type :in]))))
|
||||
request (fn [request-format response-format body]
|
||||
{:request-method :post
|
||||
:uri "/foo"
|
||||
:muuntaja/request {:format request-format}
|
||||
:muuntaja/response {:format response-format}
|
||||
:body-params body})]
|
||||
(testing "succesful call"
|
||||
(is (= {:status 200 :body {:request :json, :response :json}}
|
||||
(call (request "application/json" "application/json" {:request :json :response :json}))))
|
||||
(is (= {:status 200 :body {:request :edn, :response :json}}
|
||||
(call (request "application/edn" "application/json" {:request :edn :response :json}))))
|
||||
(is (= {:status 200 :body {:request :default, :response :default}}
|
||||
(call (request "application/transit" "application/transit" {:request :default :response :default})))))
|
||||
(testing "request validation fails"
|
||||
(is (= {:type :reitit.coercion/request-coercion :in [:request :body-params]}
|
||||
(call (request "application/edn" "application/json" {:request :json :response :json}))))
|
||||
(is (= {:type :reitit.coercion/request-coercion :in [:request :body-params]}
|
||||
(call (request "application/json" "application/json" {:request :edn :response :json}))))
|
||||
(is (= {:type :reitit.coercion/request-coercion :in [:request :body-params]}
|
||||
(call (request "application/transit" "application/json" {:request :edn :response :json})))))
|
||||
(testing "response validation fails"
|
||||
(is (= {:type :reitit.coercion/response-coercion :in [:response :body]}
|
||||
(call (request "application/json" "application/json" {:request :json :response :edn}))))
|
||||
(is (= {:type :reitit.coercion/response-coercion :in [:response :body]}
|
||||
(call (request "application/json" "application/edn" {:request :json :response :json}))))
|
||||
(is (= {:type :reitit.coercion/response-coercion :in [:response :body]}
|
||||
(call (request "application/json" "application/transit" {:request :json :response :json}))))))))))
|
||||
|
||||
|
||||
#?(:clj
|
||||
|
|
|
|||
|
|
@ -401,7 +401,7 @@
|
|||
(ring/router
|
||||
[["/parameters"
|
||||
{:post {:coercion spec/coercion
|
||||
:parameters {:request {:content {"application/json" {:x string?}}}}
|
||||
:request {:content {"application/json" {:x string?}}}
|
||||
:handler identity}}]
|
||||
["/swagger.json"
|
||||
{:get {:no-doc true
|
||||
|
|
|
|||
Loading…
Reference in a new issue