Skip to content

Commit cd8f62f

Browse files
committed
requests: Support unicode in json and data payloads.
`json.dumps()` returns a str object, and if the JSON data contains unicode then computing the length of this str -- which is used for "Content-Length" -- will return the number of characters which will be shorter than the JSON payload that is sent as bytes. The server will then read a truncated body. Fix that by converting any str payload into bytes. This fix will also convert any str object passed in by the user as the `data` argument, and that actually seems to match the upstream requests behaviour (even if it's documented that `data` should be bytes). Note that `bytes(str, "utf-8")` does not make a copy of the str data, it just makes a small bytes object that wraps the same underlying data. So it's relatively efficient. Fixes issue #251. Signed-off-by: Damien George <damien@micropython.org>
1 parent 4dfa813 commit cd8f62f

3 files changed

Lines changed: 59 additions & 3 deletions

File tree

python-ecosys/requests/manifest.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
metadata(version="0.11.0", pypi="requests")
1+
metadata(version="0.11.1", pypi="requests")
22

33
package("requests")

python-ecosys/requests/requests/__init__.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -122,8 +122,11 @@ def request(
122122
if chunked_data:
123123
if "Transfer-Encoding" not in headers and "Content-Length" not in headers:
124124
headers["Transfer-Encoding"] = "chunked"
125-
elif "Content-Length" not in headers:
126-
headers["Content-Length"] = str(len(data))
125+
else:
126+
if isinstance(data, str):
127+
data = bytes(data, "utf-8")
128+
if "Content-Length" not in headers:
129+
headers["Content-Length"] = str(len(data))
127130

128131
if "Connection" not in headers:
129132
headers["Connection"] = "close"

python-ecosys/requests/test_requests.py

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,55 @@ def test_post_json():
8484
), format_message(response)
8585

8686

87+
def test_post_json_unicode():
88+
response = requests.request("POST", "http://example.com", json="aαbβcγdδ")
89+
90+
assert response.raw._write_buffer.getvalue() == (
91+
b"POST / HTTP/1.0\r\n"
92+
+ b"Connection: close\r\n"
93+
+ b"Content-Type: application/json\r\n"
94+
+ b"Host: example.com\r\n"
95+
+ b"Content-Length: 14\r\n\r\n"
96+
+ b'"aαbβcγdδ"'
97+
), format_message(response)
98+
99+
100+
def test_post_data_str():
101+
response = requests.request("POST", "http://example.com", data="body")
102+
103+
assert response.raw._write_buffer.getvalue() == (
104+
b"POST / HTTP/1.0\r\n"
105+
+ b"Content-Length: 4\r\n"
106+
+ b"Host: example.com\r\n"
107+
+ b"Connection: close\r\n\r\n"
108+
+ b"body"
109+
), format_message(response)
110+
111+
112+
def test_post_data_str_unicode():
113+
response = requests.request("POST", "http://example.com", data="aαbβcγdδ")
114+
115+
assert response.raw._write_buffer.getvalue() == (
116+
b"POST / HTTP/1.0\r\n"
117+
+ b"Content-Length: 12\r\n"
118+
+ b"Host: example.com\r\n"
119+
+ b"Connection: close\r\n\r\n"
120+
+ b"aαbβcγdδ"
121+
), format_message(response)
122+
123+
124+
def test_post_data_bytes():
125+
response = requests.request("POST", "http://example.com", data=b"body\x01\x02\x03\xff")
126+
127+
assert response.raw._write_buffer.getvalue() == (
128+
b"POST / HTTP/1.0\r\n"
129+
+ b"Content-Length: 8\r\n"
130+
+ b"Host: example.com\r\n"
131+
+ b"Connection: close\r\n\r\n"
132+
+ b"body\x01\x02\x03\xff"
133+
), response.raw._write_buffer.getvalue()
134+
135+
87136
def test_post_chunked_data():
88137
def chunks():
89138
yield "test"
@@ -157,6 +206,10 @@ def test_do_not_modify_headers_argument():
157206
test_get_auth()
158207
test_get_custom_header()
159208
test_post_json()
209+
test_post_json_unicode()
210+
test_post_data_str()
211+
test_post_data_str_unicode()
212+
test_post_data_bytes()
160213
test_post_chunked_data()
161214
test_overwrite_get_headers()
162215
test_overwrite_post_json_headers()

0 commit comments

Comments
 (0)