Skip to content

Commit 301f316

Browse files
committed
Do not hang when deciding not to compress a file upload
This command would hang forever: ```console $ echo test > test.txt $ http -x httpbin.org/post @test.txt ``` HTTPie would read the file, compress it, then discard the compressed data because it's larger than the original. This made `request.body` an exhausted file handle, which `requests` doesn't seem to like.
1 parent 5b604c3 commit 301f316

File tree

4 files changed

+20
-1
lines changed

4 files changed

+20
-1
lines changed

httpie/uploads.py

+3
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,9 @@ def compress_request(
258258
body_bytes = request.body.encode()
259259
elif hasattr(request.body, 'read'):
260260
body_bytes = request.body.read()
261+
# The body is consumed now, so if we don't end up compressing we should
262+
# use the bytes we just read
263+
request.body = body_bytes
261264
else:
262265
body_bytes = request.body
263266
deflated_data = deflater.compress(body_bytes)

tests/fixtures/__init__.py

+2
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ def patharg(path):
2222
JSON_FILE_PATH = FIXTURES_ROOT / 'test.json'
2323
JSON_WITH_DUPE_KEYS_FILE_PATH = FIXTURES_ROOT / 'test_with_dupe_keys.json'
2424
BIN_FILE_PATH = FIXTURES_ROOT / 'test.bin'
25+
TINY_FILE_PATH = FIXTURES_ROOT / 'test_tiny.txt'
2526

2627
XML_FILES_PATH = FIXTURES_ROOT / 'xmldata'
2728
XML_FILES_VALID = list((XML_FILES_PATH / 'valid').glob('*_raw.xml'))
@@ -39,6 +40,7 @@ def patharg(path):
3940
FILE_PATH_ARG = patharg(FILE_PATH)
4041
BIN_FILE_PATH_ARG = patharg(BIN_FILE_PATH)
4142
JSON_FILE_PATH_ARG = patharg(JSON_FILE_PATH)
43+
TINY_FILE_PATH_ARG = patharg(TINY_FILE_PATH)
4244

4345
# Strip because we don't want new lines in the data so that we can
4446
# easily count occurrences also when embedded in JSON (where the new

tests/fixtures/test_tiny.txt

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
test

tests/test_compress.py

+14-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
import base64
1212
import zlib
1313

14-
from .fixtures import FILE_PATH, FILE_CONTENT
14+
from .fixtures import FILE_PATH, FILE_CONTENT, TINY_FILE_PATH_ARG
1515
from httpie.status import ExitStatus
1616
from .utils import StdinBytesIO, http, HTTP_OK, MockEnvironment
1717

@@ -138,3 +138,16 @@ def test_compress_file(httpbin_both):
138138
'multipart/form-data; boundary=')
139139
assert r.json['files'] == {}
140140
assert FILE_CONTENT not in r
141+
142+
143+
def test_compress_skip_negative_ratio_file_upload(httpbin):
144+
"""Reading the upload body but not compressing it doesn't cause a hang."""
145+
r = http(
146+
'--compress',
147+
'PUT',
148+
httpbin + '/put',
149+
f'@{TINY_FILE_PATH_ARG}',
150+
)
151+
assert HTTP_OK in r
152+
assert 'Content-Encoding' not in r.json['headers']
153+
assert r.json['data'].strip() == 'test'

0 commit comments

Comments
 (0)