diff --git a/modules/reitit-interceptors/src/reitit/http/interceptors/multipart.clj b/modules/reitit-interceptors/src/reitit/http/interceptors/multipart.clj new file mode 100644 index 00000000..12bf779e --- /dev/null +++ b/modules/reitit-interceptors/src/reitit/http/interceptors/multipart.clj @@ -0,0 +1,55 @@ +(ns reitit.http.interceptors.multipart + (:require [reitit.coercion :as coercion] + [ring.middleware.multipart-params :as multipart-params] + [clojure.spec.alpha :as s] + [spec-tools.core :as st]) + (:import (java.io File))) + +(s/def ::filename string?) +(s/def ::content-type string?) +(s/def ::tempfile (partial instance? File)) +(s/def ::bytes bytes?) +(s/def ::size int?) + +(def temp-file-part + "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"})) + +(def bytes-part + "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"})) + +(defn- coerced-request [request coercers] + (if-let [coerced (if coercers (coercion/coerce-request coercers request))] + (update request :parameters merge coerced) + request)) + +;; +;; public api +;; + +(defn multipart-interceptor + "Creates a Interceptor to handle the multipart params, based on + ring.middleware.multipart-params, taking same options. Mounts only + if endpoint has `[:parameters :multipart]` defined. Publishes coerced + parameters into `[:parameters :multipart]` under request." + ([] + (multipart-interceptor nil)) + ([options] + {:name ::multipart + :compile (fn [{:keys [parameters coercion]} opts] + (if-let [multipart (:multipart parameters)] + (let [parameter-coercion {:multipart (coercion/->ParameterCoercion + :multipart-params :string true true)} + opts (assoc opts ::coercion/parameter-coercion parameter-coercion) + coercers (if multipart (coercion/request-coercers coercion parameters opts))] + {:data {:swagger {:consumes ^:replace #{"multipart/form-data"}}} + :enter (fn [ctx] + (let [request (-> (:request ctx) + (multipart-params/multipart-params-request options) + (coerced-request coercers))] + (assoc ctx :request request)))})))})) diff --git a/modules/reitit-middleware/src/reitit/ring/middleware/multipart.clj b/modules/reitit-middleware/src/reitit/ring/middleware/multipart.clj index e6152e02..07a1d8c2 100644 --- a/modules/reitit-middleware/src/reitit/ring/middleware/multipart.clj +++ b/modules/reitit-middleware/src/reitit/ring/middleware/multipart.clj @@ -1,4 +1,4 @@ -(ns ^:no-doc reitit.ring.middleware.multipart +(ns reitit.ring.middleware.multipart (:refer-clojure :exclude [compile]) (:require [reitit.coercion :as coercion] [ring.middleware.multipart-params :as multipart-params] @@ -40,14 +40,10 @@ :wrap (fn [handler] (fn ([request] - (try - (-> request - (multipart-params/multipart-params-request options) - (coerced-request coercers) - (handler)) - (catch Exception e - (.printStackTrace e) - (throw e)))) + (-> request + (multipart-params/multipart-params-request options) + (coerced-request coercers) + (handler))) ([request respond raise] (-> request (multipart-params/multipart-params-request options) diff --git a/test/clj/reitit/http/interceptors/multipart_test.clj b/test/clj/reitit/http/interceptors/multipart_test.clj new file mode 100644 index 00000000..79a93a7c --- /dev/null +++ b/test/clj/reitit/http/interceptors/multipart_test.clj @@ -0,0 +1,3 @@ +(ns reitit.http.interceptors.multipart-test) + +;; TODO