Skip to content

Commit 1f5d1a0

Browse files
committed
Add :max-file-size option to multipart middleware
1 parent a1da756 commit 1f5d1a0

File tree

3 files changed

+43
-33
lines changed

3 files changed

+43
-33
lines changed

ring-core/project.clj

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
:dependencies [[org.clojure/clojure "1.7.0"]
88
[ring/ring-codec "1.2.0"]
99
[commons-io "2.11.0"]
10-
[commons-fileupload "1.4"]
10+
[commons-fileupload "1.5"]
1111
[crypto-random "1.2.1"]
1212
[crypto-equality "1.0.1"]]
1313
:aliases {"test-all" ["with-profile" "default:+1.8:+1.9:+1.10" "test"]}

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

+29-32
Original file line numberDiff line numberDiff line change
@@ -46,15 +46,8 @@
4646
(if (.hasNext it)
4747
(cons (.next it) (file-item-iterator-seq it)))))
4848

49-
(defn- file-item-seq
50-
"Create a seq of FileItem instances from a request context."
51-
[request progress-fn context]
52-
(let [upload (if progress-fn
53-
(doto (FileUpload.)
54-
(.setProgressListener (progress-listener request progress-fn)))
55-
(FileUpload.))]
56-
(file-item-iterator-seq
57-
(.getItemIterator ^FileUpload upload context))))
49+
(defn- file-item-seq [^FileUpload upload context]
50+
(file-item-iterator-seq (.getItemIterator upload context)))
5851

5952
(defn- parse-content-type-charset [^FileItemStream item]
6053
(some->> (.getContentType item) parsing/find-content-type-charset))
@@ -86,14 +79,12 @@
8679
:stream (.openStream item)}))
8780
(.isFormField item)])
8881

89-
(defn- parse-multipart-params
90-
"Parse a map of multipart parameters from the request."
91-
[request fallback-encoding forced-encoding store progress-fn]
92-
(->> (request-context request fallback-encoding)
93-
(file-item-seq request progress-fn)
94-
(map #(parse-file-item % store))
95-
(decode-string-values fallback-encoding forced-encoding)
96-
(reduce (fn [m [k v]] (assoc-conj m k v)) {})))
82+
(defn- make-file-upload [request {:keys [progress-fn max-file-size]}]
83+
(let [upload (FileUpload.)]
84+
(.setFileSizeMax upload (or max-file-size -1))
85+
(when progress-fn
86+
(.setProgressListener upload (progress-listener request progress-fn)))
87+
upload))
9788

9889
(defn- load-var
9990
"Returns the var named by the supplied symbol, or nil if not found. Attempts
@@ -108,27 +99,30 @@
10899
func (load-var store)]
109100
(func))))
110101

102+
(defn- parse-multipart-params
103+
"Parse a map of multipart parameters from the request."
104+
[request {:keys [encoding fallback-encoding store] :as options}]
105+
(let [store (or store @default-store)
106+
fallback-encoding (or encoding
107+
fallback-encoding
108+
(req/character-encoding request)
109+
"UTF-8")]
110+
(->> (request-context request fallback-encoding)
111+
(file-item-seq (make-file-upload request options))
112+
(map #(parse-file-item % store))
113+
(decode-string-values fallback-encoding encoding)
114+
(reduce (fn [m [k v]] (assoc-conj m k v)) {}))))
115+
111116
(defn multipart-params-request
112117
"Adds :multipart-params and :params keys to request.
113118
See: wrap-multipart-params."
114119
{:added "1.2"}
115120
([request]
116121
(multipart-params-request request {}))
117122
([request options]
118-
(let [store (or (:store options) @default-store)
119-
forced-encoding (:encoding options)
120-
req-encoding (or forced-encoding
121-
(:fallback-encoding options)
122-
(req/character-encoding request)
123-
"UTF-8")
124-
progress (:progress-fn options)
125-
params (if (multipart-form? request)
126-
(parse-multipart-params request
127-
req-encoding
128-
forced-encoding
129-
store
130-
progress)
131-
{})]
123+
(let [params (if (multipart-form? request)
124+
(parse-multipart-params request options)
125+
{})]
132126
(merge-with merge request
133127
{:multipart-params params}
134128
{:params params}))))
@@ -162,7 +156,10 @@
162156
163157
:progress-fn - a function that gets called during uploads. The
164158
function should expect four parameters: request,
165-
bytes-read, content-length, and item-count."
159+
bytes-read, content-length, and item-count.
160+
161+
:max-file-size - the maximum size allowed size of a file in bytes. If
162+
nil or omitted, there is no limit."
166163
([handler]
167164
(wrap-multipart-params handler {}))
168165
([handler options]

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

+13
Original file line numberDiff line numberDiff line change
@@ -175,3 +175,16 @@
175175
:body (string-input-stream form-body "ISO-8859-15")}
176176
request* (multipart-params-request request {:fallback-encoding "ISO-8859-15"})]
177177
(is (= (get-in request* [:multipart-params "foo"]) "äÄÖöÅå€"))))
178+
179+
(deftest test-enforced-limits
180+
(let [form-body (str "--XXXX\r\n"
181+
"Content-Disposition: form-data;"
182+
"name=\"upload\"; filename=\"test1.txt\"\r\n"
183+
"Content-Type: text/plain\r\n\r\n"
184+
"foobarbaz\r\n"
185+
"--XXXX--")
186+
request {:headers {"content-type"
187+
(str "multipart/form-data; boundary=XXXX")}
188+
:body (string-input-stream form-body)}]
189+
(is (thrown? org.apache.commons.fileupload.FileUploadBase$FileUploadIOException
190+
(multipart-params-request request {:max-file-size 6})))))

0 commit comments

Comments
 (0)