diff --git a/httpie/uploads.py b/httpie/uploads.py index 4a993b3a25..cbf7a6ed25 100644 --- a/httpie/uploads.py +++ b/httpie/uploads.py @@ -258,6 +258,9 @@ def compress_request( body_bytes = request.body.encode() elif hasattr(request.body, 'read'): body_bytes = request.body.read() + # The body is consumed now, so if we don't end up compressing we should + # use the bytes we just read + request.body = body_bytes else: body_bytes = request.body deflated_data = deflater.compress(body_bytes) diff --git a/tests/fixtures/__init__.py b/tests/fixtures/__init__.py index 6e6e73676e..d01bead6c4 100644 --- a/tests/fixtures/__init__.py +++ b/tests/fixtures/__init__.py @@ -22,6 +22,7 @@ def patharg(path): JSON_FILE_PATH = FIXTURES_ROOT / 'test.json' JSON_WITH_DUPE_KEYS_FILE_PATH = FIXTURES_ROOT / 'test_with_dupe_keys.json' BIN_FILE_PATH = FIXTURES_ROOT / 'test.bin' +TINY_FILE_PATH = FIXTURES_ROOT / 'test_tiny.txt' XML_FILES_PATH = FIXTURES_ROOT / 'xmldata' XML_FILES_VALID = list((XML_FILES_PATH / 'valid').glob('*_raw.xml')) @@ -39,6 +40,7 @@ def patharg(path): FILE_PATH_ARG = patharg(FILE_PATH) BIN_FILE_PATH_ARG = patharg(BIN_FILE_PATH) JSON_FILE_PATH_ARG = patharg(JSON_FILE_PATH) +TINY_FILE_PATH_ARG = patharg(TINY_FILE_PATH) # Strip because we don't want new lines in the data so that we can # easily count occurrences also when embedded in JSON (where the new diff --git a/tests/fixtures/test_tiny.txt b/tests/fixtures/test_tiny.txt new file mode 100644 index 0000000000..9daeafb986 --- /dev/null +++ b/tests/fixtures/test_tiny.txt @@ -0,0 +1 @@ +test diff --git a/tests/test_compress.py b/tests/test_compress.py index de5d8a7c48..e763257984 100644 --- a/tests/test_compress.py +++ b/tests/test_compress.py @@ -11,7 +11,7 @@ import base64 import zlib -from .fixtures import FILE_PATH, FILE_CONTENT +from .fixtures import FILE_PATH, FILE_CONTENT, TINY_FILE_PATH_ARG from httpie.status import ExitStatus from .utils import StdinBytesIO, http, HTTP_OK, MockEnvironment @@ -138,3 +138,16 @@ def test_compress_file(httpbin_both): 'multipart/form-data; boundary=') assert r.json['files'] == {} assert FILE_CONTENT not in r + + +def test_compress_skip_negative_ratio_file_upload(httpbin): + """Reading the upload body but not compressing it doesn't cause a hang.""" + r = http( + '--compress', + 'PUT', + httpbin + '/put', + f'@{TINY_FILE_PATH_ARG}', + ) + assert HTTP_OK in r + assert 'Content-Encoding' not in r.json['headers'] + assert r.json['data'].strip() == 'test'