diff --git a/modules/reitit-interceptors/src/reitit/http/interceptors/multipart.clj b/modules/reitit-interceptors/src/reitit/http/interceptors/multipart.clj index 4a2d4ba1..b4bd02e5 100644 --- a/modules/reitit-interceptors/src/reitit/http/interceptors/multipart.clj +++ b/modules/reitit-interceptors/src/reitit/http/interceptors/multipart.clj @@ -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"}})) diff --git a/modules/reitit-malli/src/reitit/ring/malli.cljc b/modules/reitit-malli/src/reitit/ring/malli.cljc index 1ccc1959..9815fef5 100644 --- a/modules/reitit-malli/src/reitit/ring/malli.cljc +++ b/modules/reitit-malli/src/reitit/ring/malli.cljc @@ -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?] diff --git a/test/cljc/reitit/swagger_test.clj b/test/cljc/reitit/swagger_test.clj index 542b7ebd..d2d18c31 100644 --- a/test/cljc/reitit/swagger_test.clj +++ b/test/cljc/reitit/swagger_test.clj @@ -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]))))))))