Open mynomoto opened 5 years ago
Hi,
Are you sure you want :body-params
(which doesn't do anything in pedestal-api) and don't mean :body
(the way to specify the schema for the body)?
I'm quite sure that the examples say to use :body-params
for that after content negotiation. Trying to use body fails because it has an input stream, unless some redirection happens in another interceptor before getting to the api/coerce-request
interceptor.
One example at https://github.com/oliyh/pedestal-api/blob/master/example/src/pedestal_api_example/service.clj#L41
To be clear, this is for request validation/coercion, to validate responses :body
should work.
Ah yes, you are right - ring calls it :body-params
and swagger calls it :body
hence the mismatch. pedestal-api should take care of this for you though, when you call api/defroutes
. Can you give a minimal failing example?
This is unrelated to using api/defroutes
. Calls to api/annotate
fail because of schema mismatch when running using s/with-fn-validation
.
#!/bin/sh
#_(
DEPS='
{:deps {pedestal-api {:mvn/version "0.3.4"}
io.pedestal/pedestal.jetty {:mvn/version "0.5.5"}
io.pedestal/pedestal.service {:mvn/version "0.5.5"}}}
'
OPTS='
-J-Xms256m -J-Xmx256m -J-client
'
exec clojure $OPTS -Sdeps "$DEPS" "$0" "$@"
)
(require '[pedestal-api.core :as api])
(require '[schema.core :as s])
(require '[io.pedestal.interceptor :refer [interceptor]])
(import 'java.util.UUID)
(s/defschema Pet
{:name s/Str
:type s/Str
:age s/Int})
(def create-pet
(s/with-fn-validation
(api/annotate
{:summary "Create a pet"
:parameters {:body-params Pet}
:responses {201 {:body {:id s/Uuid}}}
:operationId :create-pet}
(interceptor
{:name ::create-pet
:enter (fn [ctx]
(let [id (UUID/randomUUID)]
(assoc ctx :response
{:status 201
:body {:id id}})))}))))
Executing causes:
Exception in thread "main" Syntax error compiling at (pedestal-api-schema-problem.clj:29:3).
Input to annotate does not match schema: [(named {:parameters {:body-params disallowed-key}} doc) nil]
at clojure.lang.Compiler$InvokeExpr.eval(Compiler.java:3707)
at clojure.lang.Compiler$DefExpr.eval(Compiler.java:457)
at clojure.lang.Compiler.eval(Compiler.java:7181)
at clojure.lang.Compiler.load(Compiler.java:7635)
at clojure.lang.Compiler.loadFile(Compiler.java:7573)
at clojure.main$load_script.invokeStatic(main.clj:452)
at clojure.main$script_opt.invokeStatic(main.clj:512)
at clojure.main$script_opt.invoke(main.clj:507)
at clojure.main$main.invokeStatic(main.clj:598)
at clojure.main$main.doInvoke(main.clj:561)
at clojure.lang.RestFn.applyTo(RestFn.java:137)
at clojure.lang.Var.applyTo(Var.java:705)
at clojure.main.main(main.java:37)
Caused by: clojure.lang.ExceptionInfo: Input to annotate does not match schema: [(named {:parameters {:body-params disallowed-key}} doc) nil] {:type :schema.core/error, :schema [#schema.core.One{:schema {#schema.core.OptionalKey{:k :parameters} {#schema.core.OptionalKey{:k :body} Any, #schema.core.OptionalKey{:k :query} Any, #schema.core.OptionalKey{:k :path} Any, #schema.core.OptionalKey{:k :header} Any, #schema.core.OptionalKey{:k :formData} Any}, #schema.core.OptionalKey{:k :responses} Any, Keyword Any}, :optional? false, :name doc} #schema.core.One{:schema Any, :optional? false, :name obj}], :value [{:summary "Create a pet", :parameters {:body-params {:name java.lang.String, :type java.lang.String, :age Int}}, :responses {201 {:body {:id java.util.UUID}}}, :operationId :create-pet} #Interceptor{:name :user/create-pet}], :error [(named {:parameters {:body-params disallowed-key}} doc) nil]}
at route_swagger.doc$eval3124$annotate__3129.invoke(doc.clj:9)
at user$fn__23819$fn23820__23829$fn__23830.invoke(pedestal-api-schema-problem.clj:30)
at user$fn__23819$fn23820__23829.invoke(pedestal-api-schema-problem.clj:29)
at clojure.lang.AFn.applyToHelper(AFn.java:152)
at clojure.lang.AFn.applyTo(AFn.java:144)
at clojure.lang.AFunction$1.doInvoke(AFunction.java:31)
at clojure.lang.RestFn.invoke(RestFn.java:397)
at user$fn__23819.invokeStatic(pedestal-api-schema-problem.clj:29)
at user$fn__23819.invoke(pedestal-api-schema-problem.clj:29)
at clojure.lang.AFn.applyToHelper(AFn.java:152)
at clojure.lang.AFn.applyTo(AFn.java:144)
at clojure.lang.Compiler$InvokeExpr.eval(Compiler.java:3702)
... 12 more
The issue is that the Operation schema in ring-swagger does not accept keys :body-params
or :query-params
.
I worked around this by simply using the annotate function with the schema removed:
(defn annotate
"Attaches swagger documentation to an object."
[doc obj]
(vary-meta obj assoc ::doc doc))
The schema is not particularly useful here since it only checks for key existence. But you could certainly add in a correct schema if you choose.
I'm trying to use schema.core/with-fn-validation on my tests but I'm getting the error above. I think this schema is too strict for the use on this library but changing it would need changes on https://github.com/metosin/ring-swagger Do you have a suggestion on how to fix this? Thanks!