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'