fix: swagger multipart support

1. For spec we were including some extra stuff in the parameter
specification:

{:description "",
 :in "formData",
 :name "file",
 :properties {"bytes" {:format "byte", :type "string"},
              "content-type" {:type "string"},
              "filename" {:type "string"}},
 :required ["filename" "content-type" "bytes"],
 :type "file"}

2. For malli the :type changed from "file" to "string" because of
openapi changes. Now openapi and swagger both get the right type.

3. Test for swagger multipart support
This commit is contained in:
Joel Kaasinen 2023-03-17 14:43:49 +02:00
parent 389f4a29da
commit d8e28e153b
3 changed files with 55 additions and 4 deletions

View file

@ -19,7 +19,7 @@
"Spec for file param created by ring.middleware.multipart-params.temp-file store."
(st/spec
{:spec (s/keys :req-un [::filename ::content-type ::tempfile ::size])
:swagger/type "file"
:swagger {:type "file"}
:openapi {:type "string"
:format "binary"}}))
@ -27,7 +27,7 @@
"Spec for file param created by ring.middleware.multipart-params.byte-array store."
(st/spec
{:spec (s/keys :req-un [::filename ::content-type ::bytes])
:swagger/type "file"
:swagger {:type "file"}
:openapi {:type "string"
:format "binary"}}))

View file

@ -4,7 +4,8 @@
#?(:clj
(def temp-file-part
"Schema for file param created by ring.middleware.multipart-params.temp-file store."
[:map {:json-schema {:type "string"
[:map {:swagger {:type "file"}
:json-schema {:type "string"
:format "binary"}}
[:filename string?]
[:content-type string?]
@ -14,7 +15,8 @@
#?(:clj
(def bytes-part
"Schema for file param created by ring.middleware.multipart-params.byte-array store."
[:map {:json-schema {:type "string"
[:map {:swagger {:type "file"}
:json-schema {:type "string"
:format "binary"}}
[:filename string?]
[:content-type string?]

View file

@ -1,16 +1,27 @@
(ns reitit.swagger-test
(:require [clojure.test :refer [deftest is testing]]
[jsonista.core :as j]
[muuntaja.core :as m]
[reitit.coercion.malli :as malli]
[reitit.coercion.schema :as schema]
[reitit.coercion.spec :as spec]
[reitit.http.interceptors.multipart]
[reitit.ring :as ring]
[reitit.ring.malli]
[reitit.ring.coercion :as rrc]
[reitit.swagger :as swagger]
[reitit.swagger-ui :as swagger-ui]
[schema.core :as s]
[spec-tools.data-spec :as ds]))
(defn- normalize
"Normalize format of swagger spec by converting it to json and back.
Handles differences like :q vs \"q\" in swagger generation."
[data]
(-> data
j/write-value-as-string
(j/read-value j/keyword-keys-object-mapper)))
(def app
(ring/ring-handler
(ring/router
@ -410,3 +421,41 @@
:handler (swagger/create-swagger-handler)}}]]))
output (with-out-str (app {:request-method :get, :uri "/swagger.json"}))]
(is (.contains output "WARN")))))
(deftest multipart-test
(doseq [[coercion file-schema string-schema]
[[#'malli/coercion
reitit.ring.malli/bytes-part
:string]
[#'spec/coercion
reitit.http.interceptors.multipart/bytes-part
string?]]]
(testing coercion
(let [app (ring/ring-handler
(ring/router
[["/upload"
{:post {:decription "upload"
:coercion @coercion
:parameters {:multipart {:file file-schema
:more string-schema}}
:handler identity}}]
["/swagger.json"
{:get {:no-doc true
:handler (swagger/create-swagger-handler)}}]]
{:data {:middleware [swagger/swagger-feature]}}))
spec (-> {:request-method :get
:uri "/swagger.json"}
app
:body)]
(is (= [{:description ""
:in "formData"
:name "file"
:required true
:type "file"}
{:description ""
:in "formData"
:name "more"
:required true
:type "string"}]
(normalize
(get-in spec [:paths "/upload" :post :parameters]))))))))