Skip to content

Commit 0457c5d

Browse files
committed
Misc fixes after review
- Make CPS variant mirror the sync error handling. - Move tests to existing test file. - Rewrite tests to avoid `with-redefs`. - Make error handling customizable.customizable.
1 parent 75e6c7a commit 0457c5d

File tree

3 files changed

+74
-59
lines changed

3 files changed

+74
-59
lines changed

ring-core/src/ring/middleware/multipart_params.clj

+41-31
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,9 @@
137137
{:multipart-params params}
138138
{:params params}))))
139139

140+
(defn default-invalid-filename-handler [request e]
141+
(response/bad-request (.getMessage e)))
142+
140143
(defn wrap-multipart-params
141144
"Middleware to parse multipart parameters from a request. Adds the
142145
following keys to the request map:
@@ -146,40 +149,47 @@
146149
147150
The following options are accepted
148151
149-
:encoding - character encoding to use for multipart parsing.
150-
Overrides the encoding specified in the request. If not
151-
specified, uses the encoding specified in a part named
152-
\"_charset_\", or the content type for each part, or
153-
request character encoding if the part has no encoding,
154-
or \"UTF-8\" if no request character encoding is set.
155-
156-
:fallback-encoding - specifies the character encoding used in parsing if a
157-
part of the request does not specify encoding in its
158-
content type or no part named \"_charset_\" is present.
159-
Has no effect if :encoding is also set.
160-
161-
:store - a function that stores a file upload. The function
162-
should expect a map with :filename, :content-type and
163-
:stream keys, and its return value will be used as the
164-
value for the parameter in the multipart parameter map.
165-
The default storage function is the temp-file-store.
166-
167-
:progress-fn - a function that gets called during uploads. The
168-
function should expect four parameters: request,
169-
bytes-read, content-length, and item-count."
152+
:encoding - character encoding to use for multipart parsing.
153+
Overrides the encoding specified in the request. If not
154+
specified, uses the encoding specified in a part named
155+
\"_charset_\", or the content type for each part, or
156+
request character encoding if the part has no encoding,
157+
or \"UTF-8\" if no request character encoding is set.
158+
159+
:fallback-encoding - specifies the character encoding used in parsing if a
160+
part of the request does not specify encoding in its
161+
content type or no part named \"_charset_\" is present.
162+
Has no effect if :encoding is also set.
163+
164+
:store - a function that stores a file upload. The function
165+
should expect a map with :filename, :content-type and
166+
:stream keys, and its return value will be used as the
167+
value for the parameter in the multipart parameter map.
168+
The default storage function is the temp-file-store.
169+
170+
:progress-fn - a function that gets called during uploads. The
171+
function should expect four parameters: request,
172+
bytes-read, content-length, and item-count.
173+
174+
:invalid-filename-handler - a function that gets called when the file being uploaded
175+
has an invalid name. The function should expect two
176+
parameters: request and an exception of type
177+
InvalidFileNameException."
170178
([handler]
171179
(wrap-multipart-params handler {}))
172180
([handler options]
173181
(fn
174182
([request]
175-
(try
176-
(handler (multipart-params-request request options))
177-
(catch InvalidFileNameException e
178-
(response/bad-request (.getMessage e)))))
183+
(let [invalid-file-name-handler
184+
(:invalid-filename-handler options default-invalid-filename-handler)]
185+
(try
186+
(handler (multipart-params-request request options))
187+
(catch InvalidFileNameException e
188+
(invalid-file-name-handler request e)))))
179189
([request respond raise]
180-
(try
181-
(handler (multipart-params-request request options) respond raise)
182-
(catch InvalidFileNameException e
183-
(handler request
184-
(fn [_] (respond (response/bad-request (.getMessage e))))
185-
raise)))))))
190+
(let [invalid-file-name-handler
191+
(:invalid-filename-handler options default-invalid-filename-handler)]
192+
(try
193+
(handler (multipart-params-request request options) respond raise)
194+
(catch InvalidFileNameException e
195+
(respond (invalid-file-name-handler request e)))))))))

ring-core/test/ring/middleware/multipart_params/test/multipart_params.clj

-27
This file was deleted.

ring-core/test/ring/middleware/test/multipart_params.clj

+33-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22
(:require [clojure.test :refer :all]
33
[ring.middleware.multipart-params :refer :all]
44
[ring.middleware.multipart-params.byte-array :refer :all]
5-
[ring.util.io :refer [string-input-stream]]))
5+
[ring.util.io :refer [string-input-stream]])
6+
(:import org.apache.commons.fileupload.InvalidFileNameException))
67

78
(defn string-store [item]
89
(-> (select-keys item [:filename :content-type])
@@ -175,3 +176,34 @@
175176
:body (string-input-stream form-body "ISO-8859-15")}
176177
request* (multipart-params-request request {:fallback-encoding "ISO-8859-15"})]
177178
(is (= (get-in request* [:multipart-params "foo"]) "äÄÖöÅå€"))))
179+
180+
(deftest wrap-multipart-params-error-test
181+
(let [invalid-filename (str "foo" \u0000 ".bar")
182+
form-body (str "--XXXX\r\n"
183+
"Content-Disposition: form-data;"
184+
"name=foo; filename=" invalid-filename "\r\n"
185+
"Content-Type: text/plain\r\n\r\n"
186+
"foo\r\n"
187+
"--XXXX--")
188+
request {:headers {"content-type"
189+
(str "multipart/form-data; boundary=XXXX; charset=US-ASCII")}
190+
:body (string-input-stream form-body "ISO-8859-1")}
191+
invalid-filename-exception
192+
(try
193+
(org.apache.commons.fileupload.util.Streams/checkFileName invalid-filename)
194+
(catch Exception e
195+
e))
196+
err-response (default-invalid-filename-handler
197+
:unused-arg invalid-filename-exception)]
198+
(testing "Synchronous error response"
199+
(let [handler (wrap-multipart-params identity)]
200+
(is (= err-response (handler request)))))
201+
(testing "Asynchronous error response"
202+
(let [handler (wrap-multipart-params (fn [req respond _]
203+
(respond req)))
204+
response (promise)
205+
exception (promise)
206+
request (assoc request :body (string-input-stream form-body "ISO-8859-1"))]
207+
(handler request response exception)
208+
(is (= err-response (deref response 2000 :timed-out)))
209+
(is (not (realized? exception)))))))

0 commit comments

Comments
 (0)