Fork me on GitHub
#reitit
<
2020-06-05
>
Tanel06:06:26

Not sure if this is a bug or not, but I have an endpoint that takes in an XML message as the whole body. I have the following route (with coercion):

["/foo" {:swagger {:tags ["foo"]
                       :consumes ["application/xml"]}}
     ["/bar"
      {:post {:parameters {:body string?}
              :handler foo/bar-handler}}]]
But calling the endpoint (either via swagger or directly) throws a spec error:
$ curl -v -X POST "" -H "accept: application/json" -H "Content-Type: application/xml" -d "<?xml version=\"1.0\" encoding=\"UTF-8\"?><foo>1</foo>" | jq .

{
  "spec": "(spec-tools.core/spec {:spec clojure.core/string?, :type :string, :leaf? true})",
  "problems": [
    {
      "path": [],
      "pred": "clojure.core/string?",
      "val": null,
      "via": [],
      "in": []
    }
  ],
  "type": "reitit.coercion/request-coercion",
  "coercion": "spec",
  "value": null,
  "in": [
    "request",
    "body-params"
  ]
}
Using some? or identity instead of string? also fail. Swagger shows correctly that this endpoint consumes XML though, with a nice empty XML template where you can fill in the body.

ikitommi07:06:58

@tanel.kriik if you don’t have a middleware that reads the XML into :body-params that doesn’t work, as the params are nil. You can add the swagger parameter manually into endpoint with something like : :swagger {:parameters [{:in :body, :name "xml", :required true, :schema {}]]}and say (slurp (:body request)) to read the xml-string in your handler.

ikitommi07:06:49

… or create a middleware that checks the content-type and for xml, slurps it and pushes the string into :body-params so that the parameter coercion can read it from there.