Skip to content

Commit da0e634

Browse files
authored
Body encoding now applied and always defaults to UTF-8 (#25)
* Body encoding now always defaults to UTF-8 Was previously always encoding to system default character encoding, which is UTF-8 unless on Windows then it is windows-1252. Now: - encoding body to requested body encoding - and defaulting to UTF-8 if no body encoding requested Also: - Added extended characters to http bodies in tests to exercise body encoding/decoding - Verified :auto body decoding with an extra test Note that :auto body decoding might not be entirely correct. It will only look at content-type charset if content-type starts with "text/". Diagnosing/fixing this is out of scope for this PR. Fixes #18
1 parent 09b4e0e commit da0e634

File tree

4 files changed

+37
-24
lines changed

4 files changed

+37
-24
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
### Unreleased
22

3+
- If specified, request's body encoding is now applied, else defaults to UTF-8 ([#18](https://github.com/clj-commons/clj-http-lite/issues/18)) ([@lread](https://github.com/lread))
4+
- Quality
5+
- Automated CI testing added for Windows ([#21](https://github.com/clj-commons/clj-http-lite/issues/21)) ([@lread](https://github.com/lread))
6+
37
### 0.4.384
48

59
- Support self-signed certificates via `:insecure? true` option

src/clj_http/lite/client.clj

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@
55
[clj-http.lite.util :as util]
66
[clojure.java.io :as io]
77
[clojure.string :as str])
8-
(:import (java.net UnknownHostException))
8+
(:import (java.net UnknownHostException)
9+
(java.nio.charset Charset))
910
(:refer-clojure :exclude (get update)))
1011

1112
(set! *warn-on-reflection* true)
@@ -106,12 +107,13 @@
106107
(fn [{:keys [body body-encoding _length] :as req}]
107108
(if body
108109
(cond
109-
(string? body)
110-
(client (-> req (assoc :body (.getBytes ^String body)
111-
:character-encoding (or body-encoding
112-
"UTF-8"))))
113-
:else
114-
(client req))
110+
(string? body)
111+
(let [encoding-name (or body-encoding "UTF-8")
112+
charset (Charset/forName encoding-name)]
113+
(client (-> req (assoc :body (.getBytes ^String body charset)
114+
:character-encoding encoding-name))))
115+
:else
116+
(client req))
115117
(client req))))
116118

117119
(defn content-type-value [type]

test/clj_http/test/client.clj

Lines changed: 23 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -93,21 +93,21 @@
9393
(let [client (fn [req]
9494
(is (= "gzip, deflate"
9595
(get-in req [:headers "Accept-Encoding"])))
96-
{:body (util/gzip (util/utf8-bytes "foofoofoo"))
96+
{:body (util/gzip (util/utf8-bytes "foofoofooƒ⊙⊙"))
9797
:headers {"Content-Encoding" "gzip"}})
9898
c-client (client/wrap-decompression client)
9999
resp (c-client {})]
100-
(is (= "foofoofoo" (util/utf8-string (:body resp))))))
100+
(is (= "foofoofooƒ⊙⊙" (util/utf8-string (:body resp))))))
101101

102102
(deftest apply-on-deflated
103103
(let [client (fn [req]
104104
(is (= "gzip, deflate"
105105
(get-in req [:headers "Accept-Encoding"])))
106-
{:body (util/deflate (util/utf8-bytes "barbarbar"))
106+
{:body (util/deflate (util/utf8-bytes "barbarbar⒝⒜⒭"))
107107
:headers {"Content-Encoding" "deflate"}})
108108
c-client (client/wrap-decompression client)
109109
resp (c-client {})]
110-
(is (= "barbarbar" (util/utf8-string (:body resp))))))
110+
(is (= "barbarbar⒝⒜⒭" (util/utf8-string (:body resp))))))
111111

112112
(deftest pass-on-non-compressed
113113
(let [c-client (client/wrap-decompression (fn [req] {:body "foo"}))
@@ -141,11 +141,18 @@
141141
(is-passed client/wrap-accept-encoding
142142
{:uri "/foo"}))
143143

144-
(deftest apply-on-output-coercion
145-
(let [client (fn [req] {:body (util/utf8-bytes "foo")})
144+
(deftest apply-on-utf8-output-coercion
145+
(let [client (fn [req] {:body (util/utf8-bytes "fooⓕⓞⓞ")})
146146
o-client (client/wrap-output-coercion client)
147147
resp (o-client {:uri "/foo"})]
148-
(is (= "foo" (:body resp)))))
148+
(is (= "fooⓕⓞⓞ" (:body resp)))))
149+
150+
(deftest apply-on-other-output-coercion
151+
(let [client (fn [req] {:body (.getBytes "sõme ßÒññÝ chÀråcters" "windows-1252")
152+
:headers {"content-type" "text/foo;charset=windows-1252"}})
153+
o-client (client/wrap-output-coercion client)
154+
resp (o-client {:uri "/foo" :as :auto})]
155+
(is (= "sõme ßÒññÝ chÀråcters" (:body resp)))))
149156

150157
(deftest pass-on-no-output-coercion
151158
(let [client (fn [req] {:body nil})
@@ -158,15 +165,15 @@
158165
(is (= :thebytes (:body resp)))))
159166

160167
(deftest apply-on-input-coercion
161-
(let [i-client (client/wrap-input-coercion identity)
162-
resp (i-client {:body "foo"})
163-
resp2 (i-client {:body "foo2" :body-encoding "ASCII"})
164-
data (slurp (:body resp))
165-
data2 (slurp (:body resp2))]
166-
(is (= "UTF-8" (:character-encoding resp)))
167-
(is (= "foo" data))
168-
(is (= "ASCII" (:character-encoding resp2)))
169-
(is (= "foo2" data2))))
168+
(let [i-client (client/wrap-input-coercion identity)]
169+
(doseq [[in-body encoding expected-encoding] [["μτƒ8 нαs мαηλ ςнαяαςτεяs ൠ" nil "UTF-8"]
170+
["μτƒ8 нαs мαηλ ςнαяαςτεяs ൠ" "UTF-8" "UTF-8"]
171+
["plain text" "ASCII" "ASCII"]
172+
["sõme ßÒññÝ chÀråcters" "windows-1252" "windows-1252"]]]
173+
(let [resp (i-client {:body in-body :body-encoding encoding})
174+
decoded-body (slurp (:body resp) :encoding expected-encoding)]
175+
(is (= expected-encoding (:character-encoding resp)) "character encoding")
176+
(is (= in-body decoded-body) "body")))))
170177

171178
(deftest pass-on-no-input-coercion
172179
(is-passed client/wrap-input-coercion

test/clj_http/test/core.clj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@
165165

166166
(deftest ^{:integration true} t-save-request-obj
167167
(let [resp (request {:request-method :post :uri "/post"
168-
:body (.getBytes "foo bar")
168+
:body (.getBytes "foo bar" "UTF-8")
169169
:save-request? true})]
170170
(is (= 200 (:status resp)))
171171
(is (= {:scheme :http

0 commit comments

Comments
 (0)