summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorAndrei Zeliankou <zelenkov@nginx.com>2024-06-07 17:24:00 +0100
committerandrey-zelenkov <xim.andrew@gmail.com>2024-06-24 14:17:51 +0100
commitc7e921c7f8ee352b2b764de2c12cd39dace2e3d3 (patch)
treead11495aeb338c00e03df715627f03fb79fb0b49
parentc88265a800ccae96935f8a4f99364b22e5da3bbc (diff)
downloadunit-c7e921c7f8ee352b2b764de2c12cd39dace2e3d3.tar.gz
unit-c7e921c7f8ee352b2b764de2c12cd39dace2e3d3.tar.bz2
Tests: chunked request body
-rw-r--r--test/test_chunked.py188
-rw-r--r--test/unit/http.py2
2 files changed, 189 insertions, 1 deletions
diff --git a/test/test_chunked.py b/test/test_chunked.py
new file mode 100644
index 00000000..caa26f7e
--- /dev/null
+++ b/test/test_chunked.py
@@ -0,0 +1,188 @@
+import re
+
+import pytest
+from unit.applications.lang.python import ApplicationPython
+
+prerequisites = {'modules': {'python': 'any'}}
+
+client = ApplicationPython()
+
+
+@pytest.fixture(autouse=True)
+def setup_method_fixture():
+ client.load('mirror')
+
+ assert 'success' in client.conf(
+ {"http": {"chunked_transform": True}}, 'settings'
+ )
+
+
+def test_chunked():
+ def chunks(chunks=[]):
+ body = ''
+
+ for c in chunks:
+ body = f'{body}{len(c):x}\r\n{c}\r\n'
+
+ resp = client.get(
+ headers={
+ 'Host': 'localhost',
+ 'Connection': 'close',
+ 'Transfer-Encoding': 'chunked',
+ },
+ body=f'{body}0\r\n\r\n',
+ )
+
+ expect_body = ''.join(chunks)
+
+ assert resp['status'] == 200
+ assert resp['headers']['Content-Length'] == str(len(expect_body))
+ assert resp['body'] == expect_body
+
+ chunks()
+ chunks(['1'])
+ chunks(['0123456789'])
+ chunks(['0123456789' * 128])
+ chunks(['0123456789' * 512])
+ chunks(['0123456789' * 128, '1', '1', '0123456789' * 128, '1'])
+
+
+def test_chunked_pipeline():
+ sock = client.get(
+ no_recv=True,
+ headers={
+ 'Host': 'localhost',
+ 'Transfer-Encoding': 'chunked',
+ },
+ body='1\r\n$\r\n0\r\n\r\n',
+ )
+
+ resp = client.get(
+ sock=sock,
+ headers={
+ 'Host': 'localhost',
+ 'Transfer-Encoding': 'chunked',
+ 'Connection': 'close',
+ },
+ body='1\r\n%\r\n0\r\n\r\n',
+ raw_resp=True,
+ )
+
+ assert len(re.findall('200 OK', resp)) == 2
+ assert len(re.findall('Content-Length: 1', resp)) == 2
+ assert len(re.findall('$', resp)) == 1
+ assert len(re.findall('%', resp)) == 1
+
+
+def test_chunked_max_body_size():
+ assert 'success' in client.conf(
+ {'max_body_size': 1024, 'chunked_transform': True}, 'settings/http'
+ )
+
+ body = f'{2048:x}\r\n{"x" * 2048}\r\n0\r\n\r\n'
+
+ assert (
+ client.get(
+ headers={
+ 'Host': 'localhost',
+ 'Connection': 'close',
+ 'Transfer-Encoding': 'chunked',
+ },
+ body=body,
+ )['status']
+ == 413
+ )
+
+
+def test_chunked_after_last():
+ resp = client.get(
+ headers={
+ 'Host': 'localhost',
+ 'Connection': 'close',
+ 'Transfer-Encoding': 'chunked',
+ },
+ body='1\r\na\r\n0\r\n\r\n1\r\nb\r\n0\r\n\r\n',
+ )
+
+ assert resp['status'] == 200
+ assert resp['headers']['Content-Length'] == '1'
+ assert resp['body'] == 'a'
+
+
+def test_chunked_transform():
+ assert 'success' in client.conf(
+ {"http": {"chunked_transform": False}}, 'settings'
+ )
+
+ assert (
+ client.get(
+ headers={
+ 'Host': 'localhost',
+ 'Connection': 'close',
+ 'Transfer-Encoding': 'chunked',
+ },
+ body='0\r\n\r\n',
+ )['status']
+ == 411
+ )
+
+
+def test_chunked_invalid():
+ # invalid chunkes
+
+ def check_body(body):
+ assert (
+ client.get(
+ headers={
+ 'Host': 'localhost',
+ 'Connection': 'close',
+ 'Transfer-Encoding': 'chunked',
+ },
+ body=body,
+ )['status']
+ == 400
+ )
+
+ check_body('1\r\nblah\r\n0\r\n\r\n')
+ check_body('1\r\n\r\n1\r\n0\r\n\r\n')
+ check_body('1\r\n1\r\n\r\n0\r\n\r\n')
+
+ # invalid transfer encoding header
+
+ assert (
+ client.get(
+ headers={
+ 'Host': 'localhost',
+ 'Connection': 'close',
+ 'Transfer-Encoding': ['chunked', 'chunked'],
+ },
+ body='0\r\n\r\n',
+ )['status']
+ == 400
+ ), 'two Transfer-Encoding headers'
+
+ assert (
+ client.get(
+ headers={
+ 'Host': 'localhost',
+ 'Connection': 'close',
+ 'Transfer-Encoding': 'chunked',
+ 'Content-Length': '5',
+ },
+ body='0\r\n\r\n',
+ )['status']
+ == 400
+ ), 'Transfer-Encoding and Content-Length'
+
+ assert (
+ client.get(
+ http_10=True,
+ headers={
+ 'Host': 'localhost',
+ 'Connection': 'close',
+ 'Transfer-Encoding': 'chunked',
+ },
+ body='0\r\n\r\n',
+ )['status']
+ == 400
+ ), 'Transfer-Encoding HTTP/1.0'
diff --git a/test/unit/http.py b/test/unit/http.py
index 9401501b..e449c8b5 100644
--- a/test/unit/http.py
+++ b/test/unit/http.py
@@ -67,7 +67,7 @@ class HTTP1:
headers['Content-Type'] = content_type
- if 'Content-Length' not in headers:
+ if 'Content-Length' not in headers and 'Transfer-Encoding' not in headers:
headers['Content-Length'] = len(body)
for header, value in headers.items():