diff options
author | Konstantin Pavlov <thresh@nginx.com> | 2023-08-31 09:41:46 -0700 |
---|---|---|
committer | Konstantin Pavlov <thresh@nginx.com> | 2023-08-31 09:41:46 -0700 |
commit | c45c8919c7232eb20023484f6d1fc9f1f50395d8 (patch) | |
tree | cc12eb307c1611494948645e4b487fa06495c3d2 /test/test_proxy_chunked.py | |
parent | 88c90e1c351ab8c5bd487a5cd4b735014b08e271 (diff) | |
parent | 9b22b6957bc87b3df002d0bc691fdae6a20abdac (diff) | |
download | unit-c45c8919c7232eb20023484f6d1fc9f1f50395d8.tar.gz unit-c45c8919c7232eb20023484f6d1fc9f1f50395d8.tar.bz2 |
Merged with the default branch.1.31.0-1
Diffstat (limited to '')
-rw-r--r-- | test/test_proxy_chunked.py | 377 |
1 files changed, 184 insertions, 193 deletions
diff --git a/test/test_proxy_chunked.py b/test/test_proxy_chunked.py index f31c976a..a066e1e8 100644 --- a/test/test_proxy_chunked.py +++ b/test/test_proxy_chunked.py @@ -3,235 +3,226 @@ import select import socket import time +import pytest from conftest import run_process -from unit.applications.lang.python import TestApplicationPython -from unit.option import option +from unit.applications.lang.python import ApplicationPython from unit.utils import waitforsocket +prerequisites = {'modules': {'python': 'any'}} -class TestProxyChunked(TestApplicationPython): - prerequisites = {'modules': {'python': 'any'}} +client = ApplicationPython() +SERVER_PORT = 7999 - SERVER_PORT = 7999 - @staticmethod - def run_server(server_port, temp_dir): - sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) - sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) +@pytest.fixture(autouse=True) +def setup_method_fixture(): + run_process(run_server, SERVER_PORT) + waitforsocket(SERVER_PORT) - server_address = ('127.0.0.1', server_port) - sock.bind(server_address) - sock.listen(10) + assert 'success' in client.conf( + { + "listeners": { + "*:7080": {"pass": "routes"}, + }, + "routes": [ + {"action": {"proxy": f'http://127.0.0.1:{SERVER_PORT}'}} + ], + } + ), 'proxy initial configuration' - def recvall(sock): - buff_size = 4096 * 4096 - data = b'' - while True: - rlist = select.select([sock], [], [], 0.1) - if not rlist[0]: - break +def run_server(server_port): + sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) - part = sock.recv(buff_size) - data += part + server_address = ('127.0.0.1', server_port) + sock.bind(server_address) + sock.listen(10) - if not len(part): - break + def recvall(sock): + buff_size = 4096 * 4096 + data = b'' + while True: + rlist = select.select([sock], [], [], 0.1) - return data + if not rlist[0]: + break - while True: - connection, client_address = sock.accept() + part = sock.recv(buff_size) + data += part - req = """HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked""" + if not len(part): + break - data = recvall(connection).decode() + return data - m = re.search('\x0d\x0a\x0d\x0a(.*)', data, re.M | re.S) - if m is not None: - body = m.group(1) + while True: + connection, _ = sock.accept() - for line in re.split('\r\n', body): - add = '' - m1 = re.search(r'(.*)\sX\s(\d+)', line) + req = """HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked""" - if m1 is not None: - add = m1.group(1) * int(m1.group(2)) - else: - add = line + data = recvall(connection).decode() - req = f'{req}{add}\r\n' + m = re.search('\x0d\x0a\x0d\x0a(.*)', data, re.M | re.S) + if m is not None: + body = m.group(1) - for chunk in re.split(r'([@#])', req): - if chunk == '@' or chunk == '#': - if chunk == '#': - time.sleep(0.1) - continue + for line in re.split('\r\n', body): + add = '' + m1 = re.search(r'(.*)\sX\s(\d+)', line) - connection.sendall(chunk.encode()) + if m1 is not None: + add = m1.group(1) * int(m1.group(2)) + else: + add = line - connection.close() + req = f'{req}{add}\r\n' - def chunks(self, chunks): - body = '\r\n\r\n' + for chunk in re.split(r'([@#])', req): + if chunk == '@' or chunk == '#': + if chunk == '#': + time.sleep(0.1) + continue - for l, c in chunks: - body = f'{body}{l}\r\n{c}\r\n' + connection.sendall(chunk.encode()) - return f'{body}0\r\n\r\n' + connection.close() - def get_http10(self, *args, **kwargs): - return self.get(*args, http_10=True, **kwargs) - def setup_method(self): - run_process(self.run_server, self.SERVER_PORT, option.temp_dir) - waitforsocket(self.SERVER_PORT) +def chunks(chunks): + body = '\r\n\r\n' - assert 'success' in self.conf( - { - "listeners": { - "*:7080": {"pass": "routes"}, - }, - "routes": [ - { - "action": { - "proxy": f'http://127.0.0.1:{self.SERVER_PORT}' - } - } - ], - } - ), 'proxy initial configuration' + for l, c in chunks: + body = f'{body}{l}\r\n{c}\r\n' - def test_proxy_chunked(self): - for _ in range(10): - assert self.get_http10(body='\r\n\r\n0\r\n\r\n')['status'] == 200 + return f'{body}0\r\n\r\n' - def test_proxy_chunked_body(self): - part = '0123456789abcdef' - assert ( - self.get_http10(body=self.chunks([('1000', f'{part} X 256')]))[ - 'body' - ] - == part * 256 - ) - assert ( - self.get_http10(body=self.chunks([('100000', f'{part} X 65536')]))[ - 'body' - ] - == part * 65536 - ) - assert ( - self.get_http10( - body=self.chunks([('1000000', f'{part} X 1048576')]), - read_buffer_size=4096 * 4096, - )['body'] - == part * 1048576 - ) +def get_http10(*args, **kwargs): + return client.get(*args, http_10=True, **kwargs) - assert ( - self.get_http10( - body=self.chunks( - [('1000', f'{part} X 256'), ('1000', f'{part} X 256')] - ) - )['body'] - == part * 256 * 2 - ) - assert ( - self.get_http10( - body=self.chunks( - [ - ('100000', f'{part} X 65536'), - ('100000', f'{part} X 65536'), - ] - ) - )['body'] - == part * 65536 * 2 - ) - assert ( - self.get_http10( - body=self.chunks( - [ - ('1000000', f'{part} X 1048576'), - ('1000000', f'{part} X 1048576'), - ] - ), - read_buffer_size=4096 * 4096, - )['body'] - == part * 1048576 * 2 - ) - def test_proxy_chunked_fragmented(self): - part = '0123456789abcdef' +def test_proxy_chunked(): + for _ in range(10): + assert get_http10(body='\r\n\r\n0\r\n\r\n')['status'] == 200 - assert ( - self.get_http10( - body=self.chunks([('1', hex(i % 16)[2:]) for i in range(4096)]), - )['body'] - == part * 256 - ) - def test_proxy_chunked_send(self): - assert self.get_http10(body='\r\n\r\n@0@\r\n\r\n')['status'] == 200 - assert ( - self.get_http10( - body='\r@\n\r\n2\r@\na@b\r\n2\r\ncd@\r\n0\r@\n\r\n' - )['body'] - == 'abcd' - ) - assert ( - self.get_http10( - body='\r\n\r\n2\r#\na#b\r\n##2\r\n#cd\r\n0\r\n#\r#\n' - )['body'] - == 'abcd' - ) +def test_proxy_chunked_body(): + part = '0123456789abcdef' - def test_proxy_chunked_invalid(self): - def check_invalid(body): - assert self.get_http10(body=body)['status'] != 200 - - check_invalid('\r\n\r0') - check_invalid('\r\n\r\n\r0') - check_invalid('\r\n\r\n\r\n0') - check_invalid('\r\nContent-Length: 5\r\n\r\n0\r\n\r\n') - check_invalid('\r\n\r\n1\r\nXX\r\n0\r\n\r\n') - check_invalid('\r\n\r\n2\r\nX\r\n0\r\n\r\n') - check_invalid('\r\n\r\nH\r\nXX\r\n0\r\n\r\n') - check_invalid('\r\n\r\n0\r\nX') - - resp = self.get_http10(body='\r\n\r\n65#\r\nA X 100') - assert resp['status'] == 200, 'incomplete chunk status' - assert resp['body'][-5:] != '0\r\n\r\n', 'incomplete chunk' - - resp = self.get_http10(body='\r\n\r\n64#\r\nA X 100') - assert resp['status'] == 200, 'no zero chunk status' - assert resp['body'][-5:] != '0\r\n\r\n', 'no zero chunk' - - assert ( - self.get_http10(body='\r\n\r\n80000000\r\nA X 100')['status'] == 200 - ) - assert ( - self.get_http10(body='\r\n\r\n10000000000000000\r\nA X 100')[ - 'status' - ] - == 502 - ) - assert ( - len( - self.get_http10( - body='\r\n\r\n1000000\r\nA X 1048576\r\n1000000\r\nA X 100', - read_buffer_size=4096 * 4096, - )['body'] + assert ( + get_http10(body=chunks([('1000', f'{part} X 256')]))['body'] + == part * 256 + ) + assert ( + get_http10(body=chunks([('100000', f'{part} X 65536')]))['body'] + == part * 65536 + ) + assert ( + get_http10( + body=chunks([('1000000', f'{part} X 1048576')]), + read_buffer_size=4096 * 4096, + )['body'] + == part * 1048576 + ) + + assert ( + get_http10( + body=chunks([('1000', f'{part} X 256'), ('1000', f'{part} X 256')]) + )['body'] + == part * 256 * 2 + ) + assert ( + get_http10( + body=chunks( + [ + ('100000', f'{part} X 65536'), + ('100000', f'{part} X 65536'), + ] ) - >= 1048576 + )['body'] + == part * 65536 * 2 + ) + assert ( + get_http10( + body=chunks( + [ + ('1000000', f'{part} X 1048576'), + ('1000000', f'{part} X 1048576'), + ] + ), + read_buffer_size=4096 * 4096, + )['body'] + == part * 1048576 * 2 + ) + + +def test_proxy_chunked_fragmented(): + part = '0123456789abcdef' + + assert ( + get_http10( + body=chunks([('1', hex(i % 16)[2:]) for i in range(4096)]), + )['body'] + == part * 256 + ) + + +def test_proxy_chunked_send(): + assert get_http10(body='\r\n\r\n@0@\r\n\r\n')['status'] == 200 + assert ( + get_http10(body='\r@\n\r\n2\r@\na@b\r\n2\r\ncd@\r\n0\r@\n\r\n')['body'] + == 'abcd' + ) + assert ( + get_http10(body='\r\n\r\n2\r#\na#b\r\n##2\r\n#cd\r\n0\r\n#\r#\n')[ + 'body' + ] + == 'abcd' + ) + + +def test_proxy_chunked_invalid(): + def check_invalid(body): + assert get_http10(body=body)['status'] != 200 + + check_invalid('\r\n\r0') + check_invalid('\r\n\r\n\r0') + check_invalid('\r\n\r\n\r\n0') + check_invalid('\r\nContent-Length: 5\r\n\r\n0\r\n\r\n') + check_invalid('\r\n\r\n1\r\nXX\r\n0\r\n\r\n') + check_invalid('\r\n\r\n2\r\nX\r\n0\r\n\r\n') + check_invalid('\r\n\r\nH\r\nXX\r\n0\r\n\r\n') + check_invalid('\r\n\r\n0\r\nX') + + resp = get_http10(body='\r\n\r\n65#\r\nA X 100') + assert resp['status'] == 200, 'incomplete chunk status' + assert resp['body'][-5:] != '0\r\n\r\n', 'incomplete chunk' + + resp = get_http10(body='\r\n\r\n64#\r\nA X 100') + assert resp['status'] == 200, 'no zero chunk status' + assert resp['body'][-5:] != '0\r\n\r\n', 'no zero chunk' + + assert get_http10(body='\r\n\r\n80000000\r\nA X 100')['status'] == 200 + assert ( + get_http10(body='\r\n\r\n10000000000000000\r\nA X 100')['status'] == 502 + ) + assert ( + len( + get_http10( + body='\r\n\r\n1000000\r\nA X 1048576\r\n1000000\r\nA X 100', + read_buffer_size=4096 * 4096, + )['body'] ) - assert ( - len( - self.get_http10( - body='\r\n\r\n1000000\r\nA X 1048576\r\nXXX\r\nA X 100', - read_buffer_size=4096 * 4096, - )['body'] - ) - >= 1048576 + >= 1048576 + ) + assert ( + len( + get_http10( + body='\r\n\r\n1000000\r\nA X 1048576\r\nXXX\r\nA X 100', + read_buffer_size=4096 * 4096, + )['body'] ) + >= 1048576 + ) |