diff options
Diffstat (limited to 'test/test_proxy.py')
-rw-r--r-- | test/test_proxy.py | 805 |
1 files changed, 411 insertions, 394 deletions
diff --git a/test/test_proxy.py b/test/test_proxy.py index ad14c23d..207e90e7 100644 --- a/test/test_proxy.py +++ b/test/test_proxy.py @@ -4,487 +4,504 @@ import time import pytest from conftest import run_process -from unit.applications.lang.python import TestApplicationPython +from unit.applications.lang.python import ApplicationPython from unit.option import option from unit.utils import waitforsocket prerequisites = {'modules': {'python': 'any'}} +client = ApplicationPython() +SERVER_PORT = 7999 -class TestProxy(TestApplicationPython): - SERVER_PORT = 7999 - @pytest.fixture(autouse=True) - def setup_method_fixture(self): - run_process(self.run_server, self.SERVER_PORT) - waitforsocket(self.SERVER_PORT) +@pytest.fixture(autouse=True) +def setup_method_fixture(): + run_process(run_server, SERVER_PORT) + waitforsocket(SERVER_PORT) - python_dir = f'{option.test_dir}/python' - assert 'success' in self.conf( - { - "listeners": { - "*:7080": {"pass": "routes"}, - "*:7081": {"pass": "applications/mirror"}, + python_dir = f'{option.test_dir}/python' + assert 'success' in client.conf( + { + "listeners": { + "*:7080": {"pass": "routes"}, + "*:7081": {"pass": "applications/mirror"}, + }, + "routes": [{"action": {"proxy": "http://127.0.0.1:7081"}}], + "applications": { + "mirror": { + "type": client.get_application_type(), + "processes": {"spare": 0}, + "path": f'{python_dir}/mirror', + "working_directory": f'{python_dir}/mirror', + "module": "wsgi", + }, + "custom_header": { + "type": client.get_application_type(), + "processes": {"spare": 0}, + "path": f'{python_dir}/custom_header', + "working_directory": f'{python_dir}/custom_header', + "module": "wsgi", }, - "routes": [{"action": {"proxy": "http://127.0.0.1:7081"}}], - "applications": { - "mirror": { - "type": self.get_application_type(), - "processes": {"spare": 0}, - "path": f'{python_dir}/mirror', - "working_directory": f'{python_dir}/mirror', - "module": "wsgi", - }, - "custom_header": { - "type": self.get_application_type(), - "processes": {"spare": 0}, - "path": f'{python_dir}/custom_header', - "working_directory": f'{python_dir}/custom_header', - "module": "wsgi", - }, - "delayed": { - "type": self.get_application_type(), - "processes": {"spare": 0}, - "path": f'{python_dir}/delayed', - "working_directory": f'{python_dir}/delayed', - "module": "wsgi", - }, + "delayed": { + "type": client.get_application_type(), + "processes": {"spare": 0}, + "path": f'{python_dir}/delayed', + "working_directory": f'{python_dir}/delayed', + "module": "wsgi", }, - } - ), 'proxy initial configuration' - - @staticmethod - def run_server(server_port): - sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) - - server_address = ('', server_port) - sock.bind(server_address) - sock.listen(5) - - def recvall(sock): - buff_size = 4096 - data = b'' - while True: - part = sock.recv(buff_size) - data += part - if len(part) < buff_size: - break - return data - - req = b"""HTTP/1.1 200 OK + }, + } + ), 'proxy initial configuration' + + +def run_server(server_port): + sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + + server_address = ('', server_port) + sock.bind(server_address) + sock.listen(5) + + def recvall(sock): + buff_size = 4096 + data = b'' + while True: + part = sock.recv(buff_size) + data += part + if len(part) < buff_size: + break + return data + + req = b"""HTTP/1.1 200 OK Content-Length: 10 """ - while True: - connection, _ = sock.accept() + while True: + connection, _ = sock.accept() - data = recvall(connection).decode() + data = recvall(connection).decode() - to_send = req + to_send = req - m = re.search(r'X-Len: (\d+)', data) - if m: - to_send += b'X' * int(m.group(1)) + m = re.search(r'X-Len: (\d+)', data) + if m: + to_send += b'X' * int(m.group(1)) - connection.sendall(to_send) + connection.sendall(to_send) - connection.close() + connection.close() - def get_http10(self, *args, **kwargs): - return self.get(*args, http_10=True, **kwargs) - def post_http10(self, *args, **kwargs): - return self.post(*args, http_10=True, **kwargs) +def get_http10(*args, **kwargs): + return client.get(*args, http_10=True, **kwargs) - def test_proxy_http10(self): - for _ in range(10): - assert self.get_http10()['status'] == 200, 'status' - def test_proxy_chain(self): - assert 'success' in self.conf( - { - "listeners": { - "*:7080": {"pass": "routes/first"}, - "*:7081": {"pass": "routes/second"}, - "*:7082": {"pass": "routes/third"}, - "*:7083": {"pass": "routes/fourth"}, - "*:7084": {"pass": "routes/fifth"}, - "*:7085": {"pass": "applications/mirror"}, - }, - "routes": { - "first": [{"action": {"proxy": "http://127.0.0.1:7081"}}], - "second": [{"action": {"proxy": "http://127.0.0.1:7082"}}], - "third": [{"action": {"proxy": "http://127.0.0.1:7083"}}], - "fourth": [{"action": {"proxy": "http://127.0.0.1:7084"}}], - "fifth": [{"action": {"proxy": "http://127.0.0.1:7085"}}], - }, - "applications": { - "mirror": { - "type": self.get_application_type(), - "processes": {"spare": 0}, - "path": f'{option.test_dir}/python/mirror', - "working_directory": f'{option.test_dir}/python/mirror', - "module": "wsgi", - } - }, - } - ), 'proxy chain configuration' +def post_http10(*args, **kwargs): + return client.post(*args, http_10=True, **kwargs) - assert self.get_http10()['status'] == 200, 'status' - def test_proxy_body(self): - payload = '0123456789' - for _ in range(10): - resp = self.post_http10(body=payload) +def test_proxy_http10(): + for _ in range(10): + assert get_http10()['status'] == 200, 'status' - assert resp['status'] == 200, 'status' - assert resp['body'] == payload, 'body' - payload = 'X' * 4096 - for _ in range(10): - resp = self.post_http10(body=payload) +def test_proxy_chain(): + assert 'success' in client.conf( + { + "listeners": { + "*:7080": {"pass": "routes/first"}, + "*:7081": {"pass": "routes/second"}, + "*:7082": {"pass": "routes/third"}, + "*:7083": {"pass": "routes/fourth"}, + "*:7084": {"pass": "routes/fifth"}, + "*:7085": {"pass": "applications/mirror"}, + }, + "routes": { + "first": [{"action": {"proxy": "http://127.0.0.1:7081"}}], + "second": [{"action": {"proxy": "http://127.0.0.1:7082"}}], + "third": [{"action": {"proxy": "http://127.0.0.1:7083"}}], + "fourth": [{"action": {"proxy": "http://127.0.0.1:7084"}}], + "fifth": [{"action": {"proxy": "http://127.0.0.1:7085"}}], + }, + "applications": { + "mirror": { + "type": client.get_application_type(), + "processes": {"spare": 0}, + "path": f'{option.test_dir}/python/mirror', + "working_directory": f'{option.test_dir}/python/mirror', + "module": "wsgi", + } + }, + } + ), 'proxy chain configuration' - assert resp['status'] == 200, 'status' - assert resp['body'] == payload, 'body' + assert get_http10()['status'] == 200, 'status' - payload = 'X' * 4097 - for _ in range(10): - resp = self.post_http10(body=payload) - assert resp['status'] == 200, 'status' - assert resp['body'] == payload, 'body' +def test_proxy_body(): + payload = '0123456789' + for _ in range(10): + resp = post_http10(body=payload) - payload = 'X' * 4096 * 256 - for _ in range(10): - resp = self.post_http10(body=payload, read_buffer_size=4096 * 128) + assert resp['status'] == 200, 'status' + assert resp['body'] == payload, 'body' - assert resp['status'] == 200, 'status' - assert resp['body'] == payload, 'body' + payload = 'X' * 4096 + for _ in range(10): + resp = post_http10(body=payload) - payload = 'X' * 4096 * 257 - for _ in range(10): - resp = self.post_http10(body=payload, read_buffer_size=4096 * 128) + assert resp['status'] == 200, 'status' + assert resp['body'] == payload, 'body' - assert resp['status'] == 200, 'status' - assert resp['body'] == payload, 'body' + payload = 'X' * 4097 + for _ in range(10): + resp = post_http10(body=payload) - assert 'success' in self.conf( - {'http': {'max_body_size': 32 * 1024 * 1024}}, 'settings' - ) + assert resp['status'] == 200, 'status' + assert resp['body'] == payload, 'body' + + payload = 'X' * 4096 * 256 + for _ in range(10): + resp = post_http10(body=payload, read_buffer_size=4096 * 128) - payload = '0123456789abcdef' * 32 * 64 * 1024 - resp = self.post_http10(body=payload, read_buffer_size=1024 * 1024) assert resp['status'] == 200, 'status' assert resp['body'] == payload, 'body' - def test_proxy_parallel(self): - payload = 'X' * 4096 * 257 - buff_size = 4096 * 258 + payload = 'X' * 4096 * 257 + for _ in range(10): + resp = post_http10(body=payload, read_buffer_size=4096 * 128) - socks = [] - for i in range(10): - sock = self.post_http10( - body=f'{payload}{i}', - no_recv=True, - read_buffer_size=buff_size, - ) - socks.append(sock) + assert resp['status'] == 200, 'status' + assert resp['body'] == payload, 'body' - for i in range(10): - resp = self.recvall(socks[i], buff_size=buff_size).decode() - socks[i].close() + assert 'success' in client.conf( + {'http': {'max_body_size': 32 * 1024 * 1024}}, 'settings' + ) - resp = self._resp_to_dict(resp) + payload = '0123456789abcdef' * 32 * 64 * 1024 + resp = post_http10(body=payload, read_buffer_size=1024 * 1024) + assert resp['status'] == 200, 'status' + assert resp['body'] == payload, 'body' - assert resp['status'] == 200, 'status' - assert resp['body'] == f'{payload}{i}', 'body' - def test_proxy_header(self): - assert 'success' in self.conf( - {"pass": "applications/custom_header"}, 'listeners/*:7081' - ), 'custom_header configure' +def test_proxy_parallel(): + payload = 'X' * 4096 * 257 + buff_size = 4096 * 258 - header_value = 'blah' - assert ( - self.get_http10( - headers={'Host': 'localhost', 'Custom-Header': header_value} - )['headers']['Custom-Header'] - == header_value - ), 'custom header' + socks = [] + for i in range(10): + sock = post_http10( + body=f'{payload}{i}', + no_recv=True, + read_buffer_size=buff_size, + ) + socks.append(sock) - header_value = r"(),/:;<=>?@[\]{}\t !#$%&'*+-.^_`|~" - assert ( - self.get_http10( - headers={'Host': 'localhost', 'Custom-Header': header_value} - )['headers']['Custom-Header'] - == header_value - ), 'custom header 2' + for i in range(10): + resp = client.recvall(socks[i], buff_size=buff_size).decode() + socks[i].close() - header_value = 'X' * 4096 - assert ( - self.get_http10( - headers={'Host': 'localhost', 'Custom-Header': header_value} - )['headers']['Custom-Header'] - == header_value - ), 'custom header 3' + resp = client._resp_to_dict(resp) - header_value = 'X' * 8191 - assert ( - self.get_http10( - headers={'Host': 'localhost', 'Custom-Header': header_value} - )['headers']['Custom-Header'] - == header_value - ), 'custom header 4' + assert resp['status'] == 200, 'status' + assert resp['body'] == f'{payload}{i}', 'body' - header_value = 'X' * 8192 - assert ( - self.get_http10( - headers={'Host': 'localhost', 'Custom-Header': header_value} - )['status'] - == 431 - ), 'custom header 5' - def test_proxy_fragmented(self): - sock = self.http(b"""GET / HTT""", raw=True, no_recv=True) +def test_proxy_header(): + assert 'success' in client.conf( + {"pass": "applications/custom_header"}, 'listeners/*:7081' + ), 'custom_header configure' - time.sleep(1) + header_value = 'blah' + assert ( + get_http10( + headers={'Host': 'localhost', 'Custom-Header': header_value} + )['headers']['Custom-Header'] + == header_value + ), 'custom header' - sock.sendall("P/1.0\r\nHost: localhos".encode()) + header_value = r"(),/:;<=>?@[\]{}\t !#$%&'*+-.^_`|~" + assert ( + get_http10( + headers={'Host': 'localhost', 'Custom-Header': header_value} + )['headers']['Custom-Header'] + == header_value + ), 'custom header 2' - time.sleep(1) + header_value = 'X' * 4096 + assert ( + get_http10( + headers={'Host': 'localhost', 'Custom-Header': header_value} + )['headers']['Custom-Header'] + == header_value + ), 'custom header 3' - sock.sendall("t\r\n\r\n".encode()) + header_value = 'X' * 8191 + assert ( + get_http10( + headers={'Host': 'localhost', 'Custom-Header': header_value} + )['headers']['Custom-Header'] + == header_value + ), 'custom header 4' - assert re.search( - '200 OK', self.recvall(sock).decode() - ), 'fragmented send' - sock.close() + header_value = 'X' * 8192 + assert ( + get_http10( + headers={'Host': 'localhost', 'Custom-Header': header_value} + )['status'] + == 431 + ), 'custom header 5' - def test_proxy_fragmented_close(self): - sock = self.http(b"""GET / HTT""", raw=True, no_recv=True) - time.sleep(1) +def test_proxy_fragmented(): + sock = client.http(b"""GET / HTT""", raw=True, no_recv=True) - sock.sendall("P/1.0\r\nHo".encode()) + time.sleep(1) - sock.close() + sock.sendall("P/1.0\r\nHost: localhos".encode()) - def test_proxy_fragmented_body(self): - sock = self.http(b"""GET / HTT""", raw=True, no_recv=True) + time.sleep(1) - time.sleep(1) + sock.sendall("t\r\n\r\n".encode()) - sock.sendall("P/1.0\r\nHost: localhost\r\n".encode()) - sock.sendall("Content-Length: 30000\r\n".encode()) + assert re.search('200 OK', client.recvall(sock).decode()), 'fragmented send' + sock.close() - time.sleep(1) - sock.sendall("\r\n".encode()) - sock.sendall(("X" * 10000).encode()) +def test_proxy_fragmented_close(): + sock = client.http(b"""GET / HTT""", raw=True, no_recv=True) - time.sleep(1) + time.sleep(1) - sock.sendall(("X" * 10000).encode()) + sock.sendall("P/1.0\r\nHo".encode()) - time.sleep(1) + sock.close() - sock.sendall(("X" * 10000).encode()) - resp = self._resp_to_dict(self.recvall(sock).decode()) - sock.close() +def test_proxy_fragmented_body(): + sock = client.http(b"""GET / HTT""", raw=True, no_recv=True) - assert resp['status'] == 200, 'status' - assert resp['body'] == "X" * 30000, 'body' + time.sleep(1) - def test_proxy_fragmented_body_close(self): - sock = self.http(b"""GET / HTT""", raw=True, no_recv=True) + sock.sendall("P/1.0\r\nHost: localhost\r\n".encode()) + sock.sendall("Content-Length: 30000\r\n".encode()) - time.sleep(1) + time.sleep(1) - sock.sendall("P/1.0\r\nHost: localhost\r\n".encode()) - sock.sendall("Content-Length: 30000\r\n".encode()) + sock.sendall("\r\n".encode()) + sock.sendall(("X" * 10000).encode()) - time.sleep(1) + time.sleep(1) - sock.sendall("\r\n".encode()) - sock.sendall(("X" * 10000).encode()) + sock.sendall(("X" * 10000).encode()) - sock.close() + time.sleep(1) - def test_proxy_nowhere(self): - assert 'success' in self.conf( - [{"action": {"proxy": "http://127.0.0.1:7082"}}], 'routes' - ), 'proxy path changed' + sock.sendall(("X" * 10000).encode()) - assert self.get_http10()['status'] == 502, 'status' + resp = client._resp_to_dict(client.recvall(sock).decode()) + sock.close() - def test_proxy_ipv6(self): - assert 'success' in self.conf( - { - "*:7080": {"pass": "routes"}, - "[::1]:7081": {'application': 'mirror'}, - }, - 'listeners', - ), 'add ipv6 listener configure' + assert resp['status'] == 200, 'status' + assert resp['body'] == "X" * 30000, 'body' - assert 'success' in self.conf( - [{"action": {"proxy": "http://[::1]:7081"}}], 'routes' - ), 'proxy ipv6 configure' - assert self.get_http10()['status'] == 200, 'status' +def test_proxy_fragmented_body_close(): + sock = client.http(b"""GET / HTT""", raw=True, no_recv=True) - def test_proxy_unix(self, temp_dir): - addr = f'{temp_dir}/sock' + time.sleep(1) - assert 'success' in self.conf( - { - "*:7080": {"pass": "routes"}, - f'unix:{addr}': {'application': 'mirror'}, - }, - 'listeners', - ), 'add unix listener configure' - - assert 'success' in self.conf( - [{"action": {"proxy": f'http://unix:{addr}'}}], 'routes' - ), 'proxy unix configure' - - assert self.get_http10()['status'] == 200, 'status' - - def test_proxy_delayed(self): - assert 'success' in self.conf( - {"pass": "applications/delayed"}, 'listeners/*:7081' - ), 'delayed configure' - - body = '0123456789' * 1000 - resp = self.post_http10( - headers={ - 'Host': 'localhost', - 'Content-Length': str(len(body)), - 'X-Parts': '2', - 'X-Delay': '1', - }, - body=body, - ) + sock.sendall("P/1.0\r\nHost: localhost\r\n".encode()) + sock.sendall("Content-Length: 30000\r\n".encode()) - assert resp['status'] == 200, 'status' - assert resp['body'] == body, 'body' - - resp = self.post_http10( - headers={ - 'Host': 'localhost', - 'Content-Length': str(len(body)), - 'X-Parts': '2', - 'X-Delay': '1', - }, - body=body, - ) + time.sleep(1) - assert resp['status'] == 200, 'status' - assert resp['body'] == body, 'body' - - def test_proxy_delayed_close(self): - assert 'success' in self.conf( - {"pass": "applications/delayed"}, 'listeners/*:7081' - ), 'delayed configure' - - sock = self.post_http10( - headers={ - 'Host': 'localhost', - 'Content-Length': '10000', - 'X-Parts': '3', - 'X-Delay': '1', - }, - body='0123456789' * 1000, - no_recv=True, - ) + sock.sendall("\r\n".encode()) + sock.sendall(("X" * 10000).encode()) - assert re.search('200 OK', sock.recv(100).decode()), 'first' - sock.close() + sock.close() - sock = self.post_http10( - headers={ - 'Host': 'localhost', - 'Content-Length': '10000', - 'X-Parts': '3', - 'X-Delay': '1', - }, - body='0123456789' * 1000, - no_recv=True, - ) - assert re.search('200 OK', sock.recv(100).decode()), 'second' - sock.close() - - @pytest.mark.skip('not yet') - def test_proxy_content_length(self): - assert 'success' in self.conf( - [{"action": {"proxy": f'http://127.0.0.1:{self.SERVER_PORT}'}}], - 'routes', - ), 'proxy backend configure' - - resp = self.get_http10() - assert len(resp['body']) == 0, 'body lt Content-Length 0' - - resp = self.get_http10(headers={'Host': 'localhost', 'X-Len': '5'}) - assert len(resp['body']) == 5, 'body lt Content-Length 5' - - resp = self.get_http10(headers={'Host': 'localhost', 'X-Len': '9'}) - assert len(resp['body']) == 9, 'body lt Content-Length 9' - - resp = self.get_http10(headers={'Host': 'localhost', 'X-Len': '11'}) - assert len(resp['body']) == 10, 'body gt Content-Length 11' - - resp = self.get_http10(headers={'Host': 'localhost', 'X-Len': '15'}) - assert len(resp['body']) == 10, 'body gt Content-Length 15' - - def test_proxy_invalid(self): - def check_proxy(proxy): - assert 'error' in self.conf( - [{"action": {"proxy": proxy}}], 'routes' - ), 'proxy invalid' - - check_proxy('blah') - check_proxy('/blah') - check_proxy('unix:/blah') - check_proxy('http://blah') - check_proxy('http://127.0.0.1') - check_proxy('http://127.0.0.1:') - check_proxy('http://127.0.0.1:blah') - check_proxy('http://127.0.0.1:-1') - check_proxy('http://127.0.0.1:7080b') - check_proxy('http://[]') - check_proxy('http://[]:7080') - check_proxy('http://[:]:7080') - check_proxy('http://[::7080') - - @pytest.mark.skip('not yet') - def test_proxy_loop(self, skip_alert): - skip_alert( - r'socket.*failed', - r'accept.*failed', - r'new connections are not accepted', - ) - assert 'success' in self.conf( - { - "listeners": { - "*:7080": {"pass": "routes"}, - "*:7081": {"pass": "applications/mirror"}, - "*:7082": {"pass": "routes"}, - }, - "routes": [{"action": {"proxy": "http://127.0.0.1:7082"}}], - "applications": { - "mirror": { - "type": self.get_application_type(), - "processes": {"spare": 0}, - "path": f'{option.test_dir}/python/mirror', - "working_directory": f'{option.test_dir}/python/mirror', - "module": "wsgi", - }, +def test_proxy_nowhere(): + assert 'success' in client.conf( + [{"action": {"proxy": "http://127.0.0.1:7082"}}], 'routes' + ), 'proxy path changed' + + assert get_http10()['status'] == 502, 'status' + + +def test_proxy_ipv6(): + assert 'success' in client.conf( + { + "*:7080": {"pass": "routes"}, + "[::1]:7081": {'application': 'mirror'}, + }, + 'listeners', + ), 'add ipv6 listener configure' + + assert 'success' in client.conf( + [{"action": {"proxy": "http://[::1]:7081"}}], 'routes' + ), 'proxy ipv6 configure' + + assert get_http10()['status'] == 200, 'status' + + +def test_proxy_unix(temp_dir): + addr = f'{temp_dir}/sock' + + assert 'success' in client.conf( + { + "*:7080": {"pass": "routes"}, + f'unix:{addr}': {'application': 'mirror'}, + }, + 'listeners', + ), 'add unix listener configure' + + assert 'success' in client.conf( + [{"action": {"proxy": f'http://unix:{addr}'}}], 'routes' + ), 'proxy unix configure' + + assert get_http10()['status'] == 200, 'status' + + +def test_proxy_delayed(): + assert 'success' in client.conf( + {"pass": "applications/delayed"}, 'listeners/*:7081' + ), 'delayed configure' + + body = '0123456789' * 1000 + resp = post_http10( + headers={ + 'Host': 'localhost', + 'Content-Length': str(len(body)), + 'X-Parts': '2', + 'X-Delay': '1', + }, + body=body, + ) + + assert resp['status'] == 200, 'status' + assert resp['body'] == body, 'body' + + resp = post_http10( + headers={ + 'Host': 'localhost', + 'Content-Length': str(len(body)), + 'X-Parts': '2', + 'X-Delay': '1', + }, + body=body, + ) + + assert resp['status'] == 200, 'status' + assert resp['body'] == body, 'body' + + +def test_proxy_delayed_close(): + assert 'success' in client.conf( + {"pass": "applications/delayed"}, 'listeners/*:7081' + ), 'delayed configure' + + sock = post_http10( + headers={ + 'Host': 'localhost', + 'Content-Length': '10000', + 'X-Parts': '3', + 'X-Delay': '1', + }, + body='0123456789' * 1000, + no_recv=True, + ) + + assert re.search('200 OK', sock.recv(100).decode()), 'first' + sock.close() + + sock = post_http10( + headers={ + 'Host': 'localhost', + 'Content-Length': '10000', + 'X-Parts': '3', + 'X-Delay': '1', + }, + body='0123456789' * 1000, + no_recv=True, + ) + + assert re.search('200 OK', sock.recv(100).decode()), 'second' + sock.close() + + +@pytest.mark.skip('not yet') +def test_proxy_content_length(): + assert 'success' in client.conf( + [{"action": {"proxy": f'http://127.0.0.1:{SERVER_PORT}'}}], + 'routes', + ), 'proxy backend configure' + + resp = get_http10() + assert len(resp['body']) == 0, 'body lt Content-Length 0' + + resp = get_http10(headers={'Host': 'localhost', 'X-Len': '5'}) + assert len(resp['body']) == 5, 'body lt Content-Length 5' + + resp = get_http10(headers={'Host': 'localhost', 'X-Len': '9'}) + assert len(resp['body']) == 9, 'body lt Content-Length 9' + + resp = get_http10(headers={'Host': 'localhost', 'X-Len': '11'}) + assert len(resp['body']) == 10, 'body gt Content-Length 11' + + resp = get_http10(headers={'Host': 'localhost', 'X-Len': '15'}) + assert len(resp['body']) == 10, 'body gt Content-Length 15' + + +def test_proxy_invalid(): + def check_proxy(proxy): + assert 'error' in client.conf( + [{"action": {"proxy": proxy}}], 'routes' + ), 'proxy invalid' + + check_proxy('blah') + check_proxy('/blah') + check_proxy('unix:/blah') + check_proxy('http://blah') + check_proxy('http://127.0.0.1') + check_proxy('http://127.0.0.1:') + check_proxy('http://127.0.0.1:blah') + check_proxy('http://127.0.0.1:-1') + check_proxy('http://127.0.0.1:7080b') + check_proxy('http://[]') + check_proxy('http://[]:7080') + check_proxy('http://[:]:7080') + check_proxy('http://[::7080') + + +@pytest.mark.skip('not yet') +def test_proxy_loop(skip_alert): + skip_alert( + r'socket.*failed', + r'accept.*failed', + r'new connections are not accepted', + ) + assert 'success' in client.conf( + { + "listeners": { + "*:7080": {"pass": "routes"}, + "*:7081": {"pass": "applications/mirror"}, + "*:7082": {"pass": "routes"}, + }, + "routes": [{"action": {"proxy": "http://127.0.0.1:7082"}}], + "applications": { + "mirror": { + "type": client.get_application_type(), + "processes": {"spare": 0}, + "path": f'{option.test_dir}/python/mirror', + "working_directory": f'{option.test_dir}/python/mirror', + "module": "wsgi", }, - } - ) + }, + } + ) - self.get_http10(no_recv=True) - self.get_http10(read_timeout=1) + get_http10(no_recv=True) + get_http10(read_timeout=1) |