Skip to content

Commit b07de01

Browse files
markstodakrone
andauthored
Drop a "Content-Type" header, if any, for multipart requests (#654)
* Drop a "Content-Type" header, if any, for multipart requests * Add test coverage to avoid regression (this one is subtle) --------- Co-authored-by: Lee Hinman <[email protected]>
1 parent ef90f4e commit b07de01

File tree

2 files changed

+49
-19
lines changed

2 files changed

+49
-19
lines changed

src/clj_http/core.clj

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -609,7 +609,10 @@
609609
(if (string? body)
610610
(StringEntity. ^String body "UTF-8")
611611
(ByteArrayEntity. body))))))
612-
(doseq [[header-n header-v] headers]
612+
(doseq [[header-n header-v] headers
613+
:when (or (not multipart)
614+
(and (not= "content-type" header-n)
615+
(not= "Content-Type" header-n)))]
613616
(if (coll? header-v)
614617
(doseq [header-vth header-v]
615618
(.addHeader http-req header-n header-vth))

test/clj_http/test/client_test.clj

Lines changed: 45 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
[clj-http.conn-mgr :as conn]
55
[clj-http.test.core-test :refer [run-server]]
66
[clj-http.util :as util]
7-
[clojure.java.io :refer [resource]]
7+
[clojure.java.io :as io :refer [resource]]
88
[clojure.string :as str]
99
[clojure.test :refer :all]
1010
[cognitect.transit :as transit]
@@ -16,6 +16,7 @@
1616
java.io.PipedOutputStream
1717
java.net.UnknownHostException
1818
org.apache.http.HttpEntity
19+
org.apache.http.HttpMessage
1920
org.apache.logging.log4j.LogManager))
2021

2122
(defonce logger (LogManager/getLogger "clj-http.test.client-test"))
@@ -146,30 +147,37 @@
146147
"Verify that we went through the failure path, not the success")
147148
(is (= @fail-p expected-var *test-dynamic-var*))))))))
148149

150+
(defn retrieve-http-request-content-type-header
151+
[response]
152+
(let [http-req (get-in response [:request :http-req])]
153+
(->> (.getAllHeaders ^HttpMessage http-req)
154+
(map str)
155+
(some #(when (str/starts-with? (str/lower-case %) "content-type") %)))))
156+
149157
(deftest ^:integration multipart-async
150158
(run-server)
151-
(let [resp (promise)
152-
exception (promise)
153-
_ (request {:uri "/post" :method :post
154-
:async? true
155-
:multipart [{:name "title" :content "some-file"}
156-
{:name "Content/Type" :content "text/plain"}
157-
{:name "file"
158-
:content (clojure.java.io/file
159-
"test-resources/m.txt")}]}
160-
resp
161-
exception
162-
)]
163-
(is (= 200 (:status @resp)))
164-
(is (not (realized? exception)))
165-
#_(when (realized? exception) (prn @exception)))
159+
160+
(testing "basics"
161+
(let [resp (promise)
162+
exception (promise)
163+
_ (request {:uri "/post" :method :post
164+
:async? true
165+
:multipart [{:name "title" :content "some-file"}
166+
{:name "Content/Type" :content "text/plain"}
167+
{:name "file"
168+
:content (io/file "test-resources/m.txt")}]}
169+
resp
170+
exception)]
171+
(is (= 200 (:status (deref resp 500 :failed))))
172+
(is (not (realized? exception)))
173+
#_(when (realized? exception) (prn @exception))))
166174

167175
;; Regression Testing https://github.com/dakrone/clj-http/issues/560
168176
(testing "multipart uploads larger than 25kb"
169177
(let [resp (promise)
170178
exception (promise)
171179
;; assumption: file > 5kb
172-
file (clojure.java.io/file "test-resources/big_array_json.json")
180+
file (io/file "test-resources/big_array_json.json")
173181

174182
_ (request {:uri "/post" :method :post
175183
:async? true
@@ -181,7 +189,26 @@
181189
resp
182190
exception)]
183191
(is (= 200 (:status (deref resp 500 :failed))))
184-
(is (not (realized? exception))))))
192+
(is (not (realized? exception)))))
193+
194+
;; Find the details in https://github.com/dakrone/clj-http/pull/654
195+
(testing "existing \"Content-Type\" request header is discarded"
196+
(let [resp (request {:uri "/post" :method :post
197+
:headers {"content-type" "multipart/form-data"}
198+
:multipart [{:name "some" :content "thing"}]
199+
:save-request? true})
200+
content-type (retrieve-http-request-content-type-header resp)]
201+
(is (= 200 (:status resp)))
202+
(is (not= "multipart/form-data" content-type))
203+
(is (nil? content-type)))
204+
(let [resp (request {:uri "/post" :method :post
205+
:headers {"Content-Type" "multipart/form-data"}
206+
:multipart [{:name "some" :content "thing"}]
207+
:save-request? true})
208+
content-type (retrieve-http-request-content-type-header resp)]
209+
(is (= 200 (:status resp)))
210+
(is (not= "multipart/form-data" content-type))
211+
(is (nil? content-type)))))
185212

186213
(deftest ^:integration nil-input
187214
(is (thrown-with-msg? Exception #"Host URL cannot be nil"

0 commit comments

Comments
 (0)