diff options
author | Andrei Zeliankou <zelenkov@nginx.com> | 2023-06-14 18:20:09 +0100 |
---|---|---|
committer | Andrei Zeliankou <zelenkov@nginx.com> | 2023-06-14 18:20:09 +0100 |
commit | c183bd8749a19477390f8cb77efe5f6d223f0905 (patch) | |
tree | 4e821e9cb07be9a86bf2d442acb3ea6740ba5a99 /test/test_routing.py | |
parent | c6d05191a069ac150cc8eb2bece75cf79c0a465a (diff) | |
download | unit-c183bd8749a19477390f8cb77efe5f6d223f0905.tar.gz unit-c183bd8749a19477390f8cb77efe5f6d223f0905.tar.bz2 |
Tests: get rid of classes in test files.
Class usage came from the unittest framework and it was always redundant
after migration to the pytest. This commit removes classes from files
containing tests to make them more readable and understandable.
Diffstat (limited to 'test/test_routing.py')
-rw-r--r-- | test/test_routing.py | 3465 |
1 files changed, 1781 insertions, 1684 deletions
diff --git a/test/test_routing.py b/test/test_routing.py index 715033dd..a18edb04 100644 --- a/test/test_routing.py +++ b/test/test_routing.py @@ -1,1911 +1,2008 @@ # -*- coding: utf-8 -*- import pytest -from unit.applications.lang.python import TestApplicationPython +from unit.applications.lang.python import ApplicationPython from unit.option import option prerequisites = {'modules': {'python': 'any'}} +client = ApplicationPython() -class TestRouting(TestApplicationPython): - @pytest.fixture(autouse=True) - def setup_method_fixture(self): - assert 'success' in self.conf( - { - "listeners": {"*:7080": {"pass": "routes"}}, - "routes": [ - { - "match": {"method": "GET"}, - "action": {"return": 200}, - } - ], - "applications": {}, - } - ), 'routing configure' - def route(self, route): - return self.conf([route], 'routes') +@pytest.fixture(autouse=True) +def setup_method_fixture(): + assert 'success' in client.conf( + { + "listeners": {"*:7080": {"pass": "routes"}}, + "routes": [ + { + "match": {"method": "GET"}, + "action": {"return": 200}, + } + ], + "applications": {}, + } + ), 'routing configure' - def route_match(self, match): - assert 'success' in self.route( - {"match": match, "action": {"return": 200}} - ), 'route match configure' - def route_match_invalid(self, match): - assert 'error' in self.route( - {"match": match, "action": {"return": 200}} - ), 'route match configure invalid' +def route(route): + return client.conf([route], 'routes') - def host(self, host, status): - assert ( - self.get(headers={'Host': host, 'Connection': 'close'})['status'] - == status - ), 'match host' - def cookie(self, cookie, status): - assert ( - self.get( - headers={ - 'Host': 'localhost', - 'Cookie': cookie, - 'Connection': 'close', - }, - )['status'] - == status - ), 'match cookie' +def route_match(match): + assert 'success' in route( + {"match": match, "action": {"return": 200}} + ), 'route match configure' - def test_routes_match_method_positive(self): - assert self.get()['status'] == 200, 'GET' - assert self.post()['status'] == 404, 'POST' - def test_routes_match_method_positive_many(self): - self.route_match({"method": ["GET", "POST"]}) +def route_match_invalid(match): + assert 'error' in route( + {"match": match, "action": {"return": 200}} + ), 'route match configure invalid' - assert self.get()['status'] == 200, 'GET' - assert self.post()['status'] == 200, 'POST' - assert self.delete()['status'] == 404, 'DELETE' - def test_routes_match_method_negative(self): - self.route_match({"method": "!GET"}) +def host(host, status): + assert ( + client.get(headers={'Host': host, 'Connection': 'close'})['status'] + == status + ), 'match host' - assert self.get()['status'] == 404, 'GET' - assert self.post()['status'] == 200, 'POST' - def test_routes_match_method_negative_many(self): - self.route_match({"method": ["!GET", "!POST"]}) +def cookie(cookie, status): + assert ( + client.get( + headers={ + 'Host': 'localhost', + 'Cookie': cookie, + 'Connection': 'close', + }, + )['status'] + == status + ), 'match cookie' - assert self.get()['status'] == 404, 'GET' - assert self.post()['status'] == 404, 'POST' - assert self.delete()['status'] == 200, 'DELETE' - def test_routes_match_method_wildcard_left(self): - self.route_match({"method": "*ET"}) +def test_routes_match_method_positive(): + assert client.get()['status'] == 200, 'GET' + assert client.post()['status'] == 404, 'POST' - assert self.get()['status'] == 200, 'GET' - assert self.post()['status'] == 404, 'POST' - def test_routes_match_method_wildcard_right(self): - self.route_match({"method": "GE*"}) +def test_routes_match_method_positive_many(): + route_match({"method": ["GET", "POST"]}) - assert self.get()['status'] == 200, 'GET' - assert self.post()['status'] == 404, 'POST' + assert client.get()['status'] == 200, 'GET' + assert client.post()['status'] == 200, 'POST' + assert client.delete()['status'] == 404, 'DELETE' - def test_routes_match_method_wildcard_left_right(self): - self.route_match({"method": "*GET*"}) - assert self.get()['status'] == 200, 'GET' - assert self.post()['status'] == 404, 'POST' +def test_routes_match_method_negative(): + route_match({"method": "!GET"}) - def test_routes_match_method_wildcard(self): - self.route_match({"method": "*"}) + assert client.get()['status'] == 404, 'GET' + assert client.post()['status'] == 200, 'POST' - assert self.get()['status'] == 200, 'GET' - def test_routes_match_invalid(self): - self.route_match_invalid({"method": "**"}) +def test_routes_match_method_negative_many(): + route_match({"method": ["!GET", "!POST"]}) - def test_routes_match_valid(self): - self.route_match({"method": "blah*"}) - self.route_match({"host": "*blah*blah"}) - self.route_match({"host": "blah*blah*blah"}) - self.route_match({"host": "blah*blah*"}) + assert client.get()['status'] == 404, 'GET' + assert client.post()['status'] == 404, 'POST' + assert client.delete()['status'] == 200, 'DELETE' - def test_routes_match_empty_exact(self): - self.route_match({"uri": ""}) - assert self.get()['status'] == 404 - self.route_match({"uri": "/"}) - assert self.get()['status'] == 200 - assert self.get(url='/blah')['status'] == 404 +def test_routes_match_method_wildcard_left(): + route_match({"method": "*ET"}) - def test_routes_match_negative(self): - self.route_match({"uri": "!"}) - assert self.get()['status'] == 200 + assert client.get()['status'] == 200, 'GET' + assert client.post()['status'] == 404, 'POST' - self.route_match({"uri": "!*"}) - assert self.get()['status'] == 404 - self.route_match({"uri": "!/"}) - assert self.get()['status'] == 404 - assert self.get(url='/blah')['status'] == 200 +def test_routes_match_method_wildcard_right(): + route_match({"method": "GE*"}) - self.route_match({"uri": "!*blah"}) - assert self.get()['status'] == 200 - assert self.get(url='/bla')['status'] == 200 - assert self.get(url='/blah')['status'] == 404 - assert self.get(url='/blah1')['status'] == 200 + assert client.get()['status'] == 200, 'GET' + assert client.post()['status'] == 404, 'POST' - self.route_match({"uri": "!/blah*1*"}) - assert self.get()['status'] == 200 - assert self.get(url='/blah')['status'] == 200 - assert self.get(url='/blah1')['status'] == 404 - assert self.get(url='/blah12')['status'] == 404 - assert self.get(url='/blah2')['status'] == 200 - def test_routes_match_wildcard_middle(self): - self.route_match({"host": "ex*le"}) +def test_routes_match_method_wildcard_left_right(): + route_match({"method": "*GET*"}) - self.host('example', 200) - self.host('www.example', 404) - self.host('example.com', 404) - self.host('exampl', 404) + assert client.get()['status'] == 200, 'GET' + assert client.post()['status'] == 404, 'POST' - def test_routes_match_method_case_insensitive(self): - self.route_match({"method": "get"}) - assert self.get()['status'] == 200, 'GET' +def test_routes_match_method_wildcard(): + route_match({"method": "*"}) - def test_routes_match_wildcard_left_case_insensitive(self): - self.route_match({"method": "*get"}) - assert self.get()['status'] == 200, 'GET' + assert client.get()['status'] == 200, 'GET' - self.route_match({"method": "*et"}) - assert self.get()['status'] == 200, 'GET' - def test_routes_match_wildcard_middle_case_insensitive(self): - self.route_match({"method": "g*t"}) +def test_routes_match_invalid(): + route_match_invalid({"method": "**"}) - assert self.get()['status'] == 200, 'GET' - def test_routes_match_wildcard_right_case_insensitive(self): - self.route_match({"method": "get*"}) - assert self.get()['status'] == 200, 'GET' +def test_routes_match_valid(): + route_match({"method": "blah*"}) + route_match({"host": "*blah*blah"}) + route_match({"host": "blah*blah*blah"}) + route_match({"host": "blah*blah*"}) - self.route_match({"method": "ge*"}) - assert self.get()['status'] == 200, 'GET' - def test_routes_match_wildcard_substring_case_insensitive(self): - self.route_match({"method": "*et*"}) +def test_routes_match_empty_exact(): + route_match({"uri": ""}) + assert client.get()['status'] == 404 - assert self.get()['status'] == 200, 'GET' + route_match({"uri": "/"}) + assert client.get()['status'] == 200 + assert client.get(url='/blah')['status'] == 404 - def test_routes_match_wildcard_left_case_sensitive(self): - self.route_match({"uri": "*blah"}) - assert self.get(url='/blah')['status'] == 200, '/blah' - assert self.get(url='/BLAH')['status'] == 404, '/BLAH' +def test_routes_match_negative(): + route_match({"uri": "!"}) + assert client.get()['status'] == 200 - def test_routes_match_wildcard_middle_case_sensitive(self): - self.route_match({"uri": "/b*h"}) + route_match({"uri": "!*"}) + assert client.get()['status'] == 404 - assert self.get(url='/blah')['status'] == 200, '/blah' - assert self.get(url='/BLAH')['status'] == 404, '/BLAH' + route_match({"uri": "!/"}) + assert client.get()['status'] == 404 + assert client.get(url='/blah')['status'] == 200 - def test_route_match_wildcards_ordered(self): - self.route_match({"uri": "/a*x*y*"}) + route_match({"uri": "!*blah"}) + assert client.get()['status'] == 200 + assert client.get(url='/bla')['status'] == 200 + assert client.get(url='/blah')['status'] == 404 + assert client.get(url='/blah1')['status'] == 200 - assert self.get(url='/axy')['status'] == 200, '/axy' - assert self.get(url='/ayx')['status'] == 404, '/ayx' + route_match({"uri": "!/blah*1*"}) + assert client.get()['status'] == 200 + assert client.get(url='/blah')['status'] == 200 + assert client.get(url='/blah1')['status'] == 404 + assert client.get(url='/blah12')['status'] == 404 + assert client.get(url='/blah2')['status'] == 200 - def test_route_match_wildcards_adjust_start(self): - self.route_match({"uri": "/bla*bla*"}) - assert self.get(url='/bla_foo')['status'] == 404, '/bla_foo' +def test_routes_match_wildcard_middle(): + route_match({"host": "ex*le"}) - def test_route_match_wildcards_adjust_start_substr(self): - self.route_match({"uri": "*bla*bla*"}) + host('example', 200) + host('www.example', 404) + host('example.com', 404) + host('exampl', 404) - assert self.get(url='/bla_foo')['status'] == 404, '/bla_foo' - def test_route_match_wildcards_adjust_end(self): - self.route_match({"uri": "/bla*bla"}) +def test_routes_match_method_case_insensitive(): + route_match({"method": "get"}) - assert self.get(url='/foo_bla')['status'] == 404, '/foo_bla' + assert client.get()['status'] == 200, 'GET' - def test_routes_match_wildcard_right_case_sensitive(self): - self.route_match({"uri": "/bla*"}) - assert self.get(url='/blah')['status'] == 200, '/blah' - assert self.get(url='/BLAH')['status'] == 404, '/BLAH' +def test_routes_match_wildcard_left_case_insensitive(): + route_match({"method": "*get"}) + assert client.get()['status'] == 200, 'GET' - def test_routes_match_wildcard_substring_case_sensitive(self): - self.route_match({"uri": "*bla*"}) + route_match({"method": "*et"}) + assert client.get()['status'] == 200, 'GET' - assert self.get(url='/blah')['status'] == 200, '/blah' - assert self.get(url='/BLAH')['status'] == 404, '/BLAH' - def test_routes_match_many_wildcard_substrings_case_sensitive(self): - self.route_match({"uri": "*a*B*c*"}) +def test_routes_match_wildcard_middle_case_insensitive(): + route_match({"method": "g*t"}) - assert self.get(url='/blah-a-B-c-blah')['status'] == 200 - assert self.get(url='/a-B-c')['status'] == 200 - assert self.get(url='/aBc')['status'] == 200 - assert self.get(url='/aBCaBbc')['status'] == 200 - assert self.get(url='/ABc')['status'] == 404 + assert client.get()['status'] == 200, 'GET' - def test_routes_empty_regex(self, require): - require({'modules': {'regex': True}}) - self.route_match({"uri": "~"}) - assert self.get(url='/')['status'] == 200, 'empty regexp' - assert self.get(url='/anything')['status'] == 200, '/anything' +def test_routes_match_wildcard_right_case_insensitive(): + route_match({"method": "get*"}) + assert client.get()['status'] == 200, 'GET' - self.route_match({"uri": "!~"}) - assert self.get(url='/')['status'] == 404, 'empty regexp 2' - assert self.get(url='/nothing')['status'] == 404, '/nothing' + route_match({"method": "ge*"}) + assert client.get()['status'] == 200, 'GET' - def test_routes_bad_regex(self, require): - require({'modules': {'regex': True}}) - assert 'error' in self.route( - {"match": {"uri": "~/bl[ah"}, "action": {"return": 200}} - ), 'bad regex' +def test_routes_match_wildcard_substring_case_insensitive(): + route_match({"method": "*et*"}) - status = self.route( - {"match": {"uri": "~(?R)?z"}, "action": {"return": 200}} - ) - if 'error' not in status: - assert self.get(url='/nothing_z')['status'] == 500, '/nothing_z' + assert client.get()['status'] == 200, 'GET' - status = self.route( - {"match": {"uri": "~((?1)?z)"}, "action": {"return": 200}} - ) - if 'error' not in status: - assert self.get(url='/nothing_z')['status'] == 500, '/nothing_z' - def test_routes_match_regex_case_sensitive(self, require): - require({'modules': {'regex': True}}) +def test_routes_match_wildcard_left_case_sensitive(): + route_match({"uri": "*blah"}) - self.route_match({"uri": "~/bl[ah]"}) + assert client.get(url='/blah')['status'] == 200, '/blah' + assert client.get(url='/BLAH')['status'] == 404, '/BLAH' - assert self.get(url='/rlah')['status'] == 404, '/rlah' - assert self.get(url='/blah')['status'] == 200, '/blah' - assert self.get(url='/blh')['status'] == 200, '/blh' - assert self.get(url='/BLAH')['status'] == 404, '/BLAH' - def test_routes_match_regex_negative_case_sensitive(self, require): - require({'modules': {'regex': True}}) +def test_routes_match_wildcard_middle_case_sensitive(): + route_match({"uri": "/b*h"}) - self.route_match({"uri": "!~/bl[ah]"}) + assert client.get(url='/blah')['status'] == 200, '/blah' + assert client.get(url='/BLAH')['status'] == 404, '/BLAH' - assert self.get(url='/rlah')['status'] == 200, '/rlah' - assert self.get(url='/blah')['status'] == 404, '/blah' - assert self.get(url='/blh')['status'] == 404, '/blh' - assert self.get(url='/BLAH')['status'] == 200, '/BLAH' - def test_routes_pass_encode(self): - python_dir = f'{option.test_dir}/python' +def test_route_match_wildcards_ordered(): + route_match({"uri": "/a*x*y*"}) - def check_pass(path, name): - assert 'success' in self.conf( - { - "listeners": {"*:7080": {"pass": f'applications/{path}'}}, - "applications": { - name: { - "type": self.get_application_type(), - "processes": {"spare": 0}, - "path": f'{python_dir}/empty', - "working_directory": f'{python_dir}/empty', - "module": "wsgi", - } - }, - } - ) + assert client.get(url='/axy')['status'] == 200, '/axy' + assert client.get(url='/ayx')['status'] == 404, '/ayx' - assert self.get()['status'] == 200 - check_pass("%25", "%") - check_pass("blah%2Fblah", "blah/blah") - check_pass("%2Fblah%2F%2Fblah%2F", "/blah//blah/") - check_pass("%20blah%252Fblah%7E", " blah%2Fblah~") +def test_route_match_wildcards_adjust_start(): + route_match({"uri": "/bla*bla*"}) - def check_pass_error(path, name): - assert 'error' in self.conf( - { - "listeners": {"*:7080": {"pass": f'applications/{path}'}}, - "applications": { - name: { - "type": self.get_application_type(), - "processes": {"spare": 0}, - "path": f'{python_dir}/empty', - "working_directory": f'{python_dir}/empty', - "module": "wsgi", - } - }, - } - ) + assert client.get(url='/bla_foo')['status'] == 404, '/bla_foo' - check_pass_error("%", "%") - check_pass_error("%1", "%1") - def test_routes_absent(self): - assert 'success' in self.conf( - { - "listeners": {"*:7081": {"pass": "applications/empty"}}, - "applications": { - "empty": { - "type": self.get_application_type(), - "processes": {"spare": 0}, - "path": f'{option.test_dir}/python/empty', - "working_directory": f'{option.test_dir}/python/empty', - "module": "wsgi", - } - }, - } - ) +def test_route_match_wildcards_adjust_start_substr(): + route_match({"uri": "*bla*bla*"}) - assert self.get(port=7081)['status'] == 200, 'routes absent' + assert client.get(url='/bla_foo')['status'] == 404, '/bla_foo' - def test_routes_pass_invalid(self): - assert 'error' in self.conf( - {"pass": "routes/blah"}, 'listeners/*:7080' - ), 'routes invalid' - def test_route_empty(self): - assert 'success' in self.conf( - { - "listeners": {"*:7080": {"pass": "routes/main"}}, - "routes": {"main": []}, - "applications": {}, - } - ), 'route empty configure' +def test_route_match_wildcards_adjust_end(): + route_match({"uri": "/bla*bla"}) - assert self.get()['status'] == 404, 'route empty' + assert client.get(url='/foo_bla')['status'] == 404, '/foo_bla' - def test_routes_route_empty(self): - assert 'success' in self.conf( - {}, 'listeners' - ), 'routes empty listeners configure' - assert 'success' in self.conf({}, 'routes'), 'routes empty configure' +def test_routes_match_wildcard_right_case_sensitive(): + route_match({"uri": "/bla*"}) - def test_routes_route_match_absent(self): - assert 'success' in self.conf( - [{"action": {"return": 200}}], 'routes' - ), 'route match absent configure' + assert client.get(url='/blah')['status'] == 200, '/blah' + assert client.get(url='/BLAH')['status'] == 404, '/BLAH' - assert self.get()['status'] == 200, 'route match absent' - def test_routes_route_action_absent(self, skip_alert): - skip_alert(r'failed to apply new conf') +def test_routes_match_wildcard_substring_case_sensitive(): + route_match({"uri": "*bla*"}) - assert 'error' in self.conf( - [{"match": {"method": "GET"}}], 'routes' - ), 'route pass absent configure' + assert client.get(url='/blah')['status'] == 200, '/blah' + assert client.get(url='/BLAH')['status'] == 404, '/BLAH' - def test_routes_route_pass(self): - assert 'success' in self.conf( - { - "applications": { - "app": { - "type": self.get_application_type(), - "processes": {"spare": 0}, - "path": "/app", - "module": "wsgi", - } - }, - "upstreams": { - "one": { - "servers": { - "127.0.0.1:7081": {}, - "127.0.0.1:7082": {}, - }, - }, - "two": { - "servers": { - "127.0.0.1:7081": {}, - "127.0.0.1:7082": {}, - }, - }, - }, - } - ) - assert 'success' in self.conf( - [{"action": {"pass": "routes"}}], 'routes' - ) - assert 'success' in self.conf( - [{"action": {"pass": "applications/app"}}], 'routes' - ) - assert 'success' in self.conf( - [{"action": {"pass": "upstreams/one"}}], 'routes' - ) +def test_routes_match_many_wildcard_substrings_case_sensitive(): + route_match({"uri": "*a*B*c*"}) + + assert client.get(url='/blah-a-B-c-blah')['status'] == 200 + assert client.get(url='/a-B-c')['status'] == 200 + assert client.get(url='/aBc')['status'] == 200 + assert client.get(url='/aBCaBbc')['status'] == 200 + assert client.get(url='/ABc')['status'] == 404 + + +def test_routes_empty_regex(require): + require({'modules': {'regex': True}}) + + route_match({"uri": "~"}) + assert client.get(url='/')['status'] == 200, 'empty regexp' + assert client.get(url='/anything')['status'] == 200, '/anything' + + route_match({"uri": "!~"}) + assert client.get(url='/')['status'] == 404, 'empty regexp 2' + assert client.get(url='/nothing')['status'] == 404, '/nothing' + + +def test_routes_bad_regex(require): + require({'modules': {'regex': True}}) + + assert 'error' in route( + {"match": {"uri": "~/bl[ah"}, "action": {"return": 200}} + ), 'bad regex' + + status = route({"match": {"uri": "~(?R)?z"}, "action": {"return": 200}}) + if 'error' not in status: + assert client.get(url='/nothing_z')['status'] == 500, '/nothing_z' - def test_routes_route_pass_absent(self): - assert 'error' in self.conf( - [{"match": {"method": "GET"}, "action": {}}], 'routes' - ), 'route pass absent configure' + status = route({"match": {"uri": "~((?1)?z)"}, "action": {"return": 200}}) + if 'error' not in status: + assert client.get(url='/nothing_z')['status'] == 500, '/nothing_z' - def test_routes_route_pass_invalid(self): - assert 'success' in self.conf( + +def test_routes_match_regex_case_sensitive(require): + require({'modules': {'regex': True}}) + + route_match({"uri": "~/bl[ah]"}) + + assert client.get(url='/rlah')['status'] == 404, '/rlah' + assert client.get(url='/blah')['status'] == 200, '/blah' + assert client.get(url='/blh')['status'] == 200, '/blh' + assert client.get(url='/BLAH')['status'] == 404, '/BLAH' + + +def test_routes_match_regex_negative_case_sensitive(require): + require({'modules': {'regex': True}}) + + route_match({"uri": "!~/bl[ah]"}) + + assert client.get(url='/rlah')['status'] == 200, '/rlah' + assert client.get(url='/blah')['status'] == 404, '/blah' + assert client.get(url='/blh')['status'] == 404, '/blh' + assert client.get(url='/BLAH')['status'] == 200, '/BLAH' + + +def test_routes_pass_encode(): + python_dir = f'{option.test_dir}/python' + + def check_pass(path, name): + assert 'success' in client.conf( { + "listeners": {"*:7080": {"pass": f'applications/{path}'}}, "applications": { - "app": { - "type": self.get_application_type(), + name: { + "type": client.get_application_type(), "processes": {"spare": 0}, - "path": "/app", + "path": f'{python_dir}/empty', + "working_directory": f'{python_dir}/empty', "module": "wsgi", } }, - "upstreams": { - "one": { - "servers": { - "127.0.0.1:7081": {}, - "127.0.0.1:7082": {}, - }, - }, - "two": { - "servers": { - "127.0.0.1:7081": {}, - "127.0.0.1:7082": {}, - }, - }, - }, } ) - assert 'error' in self.conf( - [{"action": {"pass": "blah"}}], 'routes' - ), 'route pass invalid' - assert 'error' in self.conf( - [{"action": {"pass": "routes/blah"}}], 'routes' - ), 'route pass routes invalid' - assert 'error' in self.conf( - [{"action": {"pass": "applications/blah"}}], 'routes' - ), 'route pass applications invalid' - assert 'error' in self.conf( - [{"action": {"pass": "upstreams/blah"}}], 'routes' - ), 'route pass upstreams invalid' - - def test_routes_action_unique(self, temp_dir): - assert 'success' in self.conf( + assert client.get()['status'] == 200 + + check_pass("%25", "%") + check_pass("blah%2Fblah", "blah/blah") + check_pass("%2Fblah%2F%2Fblah%2F", "/blah//blah/") + check_pass("%20blah%252Fblah%7E", " blah%2Fblah~") + + def check_pass_error(path, name): + assert 'error' in client.conf( { - "listeners": { - "*:7080": {"pass": "routes"}, - "*:7081": {"pass": "applications/app"}, - }, - "routes": [{"action": {"proxy": "http://127.0.0.1:7081"}}], + "listeners": {"*:7080": {"pass": f'applications/{path}'}}, "applications": { - "app": { - "type": self.get_application_type(), + name: { + "type": client.get_application_type(), "processes": {"spare": 0}, - "path": "/app", + "path": f'{python_dir}/empty', + "working_directory": f'{python_dir}/empty', "module": "wsgi", } }, } ) - assert 'error' in self.conf( - {"proxy": "http://127.0.0.1:7081", "share": temp_dir}, - 'routes/0/action', - ), 'proxy share' - assert 'error' in self.conf( - { - "proxy": "http://127.0.0.1:7081", - "pass": "applications/app", + check_pass_error("%", "%") + check_pass_error("%1", "%1") + + +def test_routes_absent(): + assert 'success' in client.conf( + { + "listeners": {"*:7081": {"pass": "applications/empty"}}, + "applications": { + "empty": { + "type": client.get_application_type(), + "processes": {"spare": 0}, + "path": f'{option.test_dir}/python/empty', + "working_directory": f'{option.test_dir}/python/empty', + "module": "wsgi", + } }, - 'routes/0/action', - ), 'proxy pass' - assert 'error' in self.conf( - {"share": temp_dir, "pass": "applications/app"}, - 'routes/0/action', - ), 'share pass' - - def test_routes_rules_two(self): - assert 'success' in self.conf( - [ - {"match": {"method": "GET"}, "action": {"return": 200}}, - {"match": {"method": "POST"}, "action": {"return": 201}}, - ], - 'routes', - ), 'rules two configure' + } + ) - assert self.get()['status'] == 200, 'rules two match first' - assert self.post()['status'] == 201, 'rules two match second' + assert client.get(port=7081)['status'] == 200, 'routes absent' - def test_routes_two(self): - assert 'success' in self.conf( - { - "listeners": {"*:7080": {"pass": "routes/first"}}, - "routes": { - "first": [ - { - "match": {"method": "GET"}, - "action": {"pass": "routes/second"}, - } - ], - "second": [ - { - "match": {"host": "localhost"}, - "action": {"return": 200}, - } - ], + +def test_routes_pass_invalid(): + assert 'error' in client.conf( + {"pass": "routes/blah"}, 'listeners/*:7080' + ), 'routes invalid' + + +def test_route_empty(): + assert 'success' in client.conf( + { + "listeners": {"*:7080": {"pass": "routes/main"}}, + "routes": {"main": []}, + "applications": {}, + } + ), 'route empty configure' + + assert client.get()['status'] == 404, 'route empty' + + +def test_routes_route_empty(): + assert 'success' in client.conf( + {}, 'listeners' + ), 'routes empty listeners configure' + + assert 'success' in client.conf({}, 'routes'), 'routes empty configure' + + +def test_routes_route_match_absent(): + assert 'success' in client.conf( + [{"action": {"return": 200}}], 'routes' + ), 'route match absent configure' + + assert client.get()['status'] == 200, 'route match absent' + + +def test_routes_route_action_absent(skip_alert): + skip_alert(r'failed to apply new conf') + + assert 'error' in client.conf( + [{"match": {"method": "GET"}}], 'routes' + ), 'route pass absent configure' + + +def test_routes_route_pass(): + assert 'success' in client.conf( + { + "applications": { + "app": { + "type": client.get_application_type(), + "processes": {"spare": 0}, + "path": "/app", + "module": "wsgi", + } + }, + "upstreams": { + "one": { + "servers": { + "127.0.0.1:7081": {}, + "127.0.0.1:7082": {}, + }, }, - "applications": {}, - } - ), 'routes two configure' + "two": { + "servers": { + "127.0.0.1:7081": {}, + "127.0.0.1:7082": {}, + }, + }, + }, + } + ) + + assert 'success' in client.conf([{"action": {"pass": "routes"}}], 'routes') + assert 'success' in client.conf( + [{"action": {"pass": "applications/app"}}], 'routes' + ) + assert 'success' in client.conf( + [{"action": {"pass": "upstreams/one"}}], 'routes' + ) + + +def test_routes_route_pass_absent(): + assert 'error' in client.conf( + [{"match": {"method": "GET"}, "action": {}}], 'routes' + ), 'route pass absent configure' + + +def test_routes_route_pass_invalid(): + assert 'success' in client.conf( + { + "applications": { + "app": { + "type": client.get_application_type(), + "processes": {"spare": 0}, + "path": "/app", + "module": "wsgi", + } + }, + "upstreams": { + "one": { + "servers": { + "127.0.0.1:7081": {}, + "127.0.0.1:7082": {}, + }, + }, + "two": { + "servers": { + "127.0.0.1:7081": {}, + "127.0.0.1:7082": {}, + }, + }, + }, + } + ) + + assert 'error' in client.conf( + [{"action": {"pass": "blah"}}], 'routes' + ), 'route pass invalid' + assert 'error' in client.conf( + [{"action": {"pass": "routes/blah"}}], 'routes' + ), 'route pass routes invalid' + assert 'error' in client.conf( + [{"action": {"pass": "applications/blah"}}], 'routes' + ), 'route pass applications invalid' + assert 'error' in client.conf( + [{"action": {"pass": "upstreams/blah"}}], 'routes' + ), 'route pass upstreams invalid' + + +def test_routes_action_unique(temp_dir): + assert 'success' in client.conf( + { + "listeners": { + "*:7080": {"pass": "routes"}, + "*:7081": {"pass": "applications/app"}, + }, + "routes": [{"action": {"proxy": "http://127.0.0.1:7081"}}], + "applications": { + "app": { + "type": client.get_application_type(), + "processes": {"spare": 0}, + "path": "/app", + "module": "wsgi", + } + }, + } + ) + + assert 'error' in client.conf( + {"proxy": "http://127.0.0.1:7081", "share": temp_dir}, + 'routes/0/action', + ), 'proxy share' + assert 'error' in client.conf( + { + "proxy": "http://127.0.0.1:7081", + "pass": "applications/app", + }, + 'routes/0/action', + ), 'proxy pass' + assert 'error' in client.conf( + {"share": temp_dir, "pass": "applications/app"}, + 'routes/0/action', + ), 'share pass' + + +def test_routes_rules_two(): + assert 'success' in client.conf( + [ + {"match": {"method": "GET"}, "action": {"return": 200}}, + {"match": {"method": "POST"}, "action": {"return": 201}}, + ], + 'routes', + ), 'rules two configure' + + assert client.get()['status'] == 200, 'rules two match first' + assert client.post()['status'] == 201, 'rules two match second' + + +def test_routes_two(): + assert 'success' in client.conf( + { + "listeners": {"*:7080": {"pass": "routes/first"}}, + "routes": { + "first": [ + { + "match": {"method": "GET"}, + "action": {"pass": "routes/second"}, + } + ], + "second": [ + { + "match": {"host": "localhost"}, + "action": {"return": 200}, + } + ], + }, + "applications": {}, + } + ), 'routes two configure' - assert self.get()['status'] == 200, 'routes two' + assert client.get()['status'] == 200, 'routes two' - def test_routes_match_host_positive(self): - self.route_match({"host": "localhost"}) - assert self.get()['status'] == 200, 'localhost' - self.host('localhost.', 200) - self.host('localhost.', 200) - self.host('.localhost', 404) - self.host('www.localhost', 404) - self.host('localhost1', 404) +def test_routes_match_host_positive(): + route_match({"host": "localhost"}) - @pytest.mark.skip('not yet') - def test_routes_match_host_absent(self): - self.route_match({"host": "localhost"}) + assert client.get()['status'] == 200, 'localhost' + host('localhost.', 200) + host('localhost.', 200) + host('.localhost', 404) + host('www.localhost', 404) + host('localhost1', 404) - assert ( - self.get(headers={'Connection': 'close'})['status'] == 400 - ), 'match host absent' - def test_routes_match_host_ipv4(self): - self.route_match({"host": "127.0.0.1"}) +@pytest.mark.skip('not yet') +def test_routes_match_host_absent(): + route_match({"host": "localhost"}) - self.host('127.0.0.1', 200) - self.host('127.0.0.1:7080', 200) + assert ( + client.get(headers={'Connection': 'close'})['status'] == 400 + ), 'match host absent' - def test_routes_match_host_ipv6(self): - self.route_match({"host": "[::1]"}) - self.host('[::1]', 200) - self.host('[::1]:7080', 200) +def test_routes_match_host_ipv4(): + route_match({"host": "127.0.0.1"}) - def test_routes_match_host_positive_many(self): - self.route_match({"host": ["localhost", "example.com"]}) + host('127.0.0.1', 200) + host('127.0.0.1:7080', 200) - assert self.get()['status'] == 200, 'localhost' - self.host('example.com', 200) - def test_routes_match_host_positive_and_negative(self): - self.route_match({"host": ["*example.com", "!www.example.com"]}) +def test_routes_match_host_ipv6(): + route_match({"host": "[::1]"}) - assert self.get()['status'] == 404, 'localhost' - self.host('example.com', 200) - self.host('www.example.com', 404) - self.host('!www.example.com', 200) + host('[::1]', 200) + host('[::1]:7080', 200) - def test_routes_match_host_positive_and_negative_wildcard(self): - self.route_match({"host": ["*example*", "!www.example*"]}) - self.host('example.com', 200) - self.host('www.example.com', 404) +def test_routes_match_host_positive_many(): + route_match({"host": ["localhost", "example.com"]}) - def test_routes_match_host_case_insensitive(self): - self.route_match({"host": "Example.com"}) + assert client.get()['status'] == 200, 'localhost' + host('example.com', 200) - self.host('example.com', 200) - self.host('EXAMPLE.COM', 200) - def test_routes_match_host_port(self): - self.route_match({"host": "example.com"}) +def test_routes_match_host_positive_and_negative(): + route_match({"host": ["*example.com", "!www.example.com"]}) - self.host('example.com:7080', 200) + assert client.get()['status'] == 404, 'localhost' + host('example.com', 200) + host('www.example.com', 404) + host('!www.example.com', 200) - def test_routes_match_host_empty(self): - self.route_match({"host": ""}) - self.host('', 200) - assert ( - self.get(http_10=True, headers={})['status'] == 200 - ), 'match host empty 2' - assert self.get()['status'] == 404, 'match host empty 3' - - def test_routes_match_uri_positive(self): - self.route_match({"uri": ["/blah", "/slash/"]}) - - assert self.get()['status'] == 404, '/' - assert self.get(url='/blah')['status'] == 200, '/blah' - assert self.get(url='/blah#foo')['status'] == 200, '/blah#foo' - assert self.get(url='/blah?var')['status'] == 200, '/blah?var' - assert self.get(url='//blah')['status'] == 200, '//blah' - assert self.get(url='/slash/foo/../')['status'] == 200, 'relative' - assert self.get(url='/slash/./')['status'] == 200, '/slash/./' - assert self.get(url='/slash//.//')['status'] == 200, 'adjacent slashes' - assert self.get(url='/%')['status'] == 400, 'percent' - assert self.get(url='/%1')['status'] == 400, 'percent digit' - assert self.get(url='/%A')['status'] == 400, 'percent letter' - assert self.get(url='/slash/.?args')['status'] == 200, 'dot args' - assert self.get(url='/slash/.#frag')['status'] == 200, 'dot frag' - assert ( - self.get(url='/slash/foo/..?args')['status'] == 200 - ), 'dot dot args' - assert ( - self.get(url='/slash/foo/..#frag')['status'] == 200 - ), 'dot dot frag' - assert self.get(url='/slash/.')['status'] == 200, 'trailing dot' - assert ( - self.get(url='/slash/foo/..')['status'] == 200 - ), 'trailing dot dot' +def test_routes_match_host_positive_and_negative_wildcard(): + route_match({"host": ["*example*", "!www.example*"]}) - def test_routes_match_uri_case_sensitive(self): - self.route_match({"uri": "/BLAH"}) + host('example.com', 200) + host('www.example.com', 404) - assert self.get(url='/blah')['status'] == 404, '/blah' - assert self.get(url='/BlaH')['status'] == 404, '/BlaH' - assert self.get(url='/BLAH')['status'] == 200, '/BLAH' - def test_routes_match_uri_normalize(self): - self.route_match({"uri": "/blah"}) +def test_routes_match_host_case_insensitive(): + route_match({"host": "Example.com"}) - assert self.get(url='/%62%6c%61%68')['status'] == 200, 'normalize' + host('example.com', 200) + host('EXAMPLE.COM', 200) - def test_routes_match_empty_array(self): - self.route_match({"uri": []}) - assert self.get(url='/blah')['status'] == 200, 'empty array' +def test_routes_match_host_port(): + route_match({"host": "example.com"}) - def test_routes_reconfigure(self): - assert 'success' in self.conf([], 'routes'), 'redefine' - assert self.get()['status'] == 404, 'redefine request' + host('example.com:7080', 200) - assert 'success' in self.conf( - [{"action": {"return": 200}}], 'routes' - ), 'redefine 2' - assert self.get()['status'] == 200, 'redefine request 2' - assert 'success' in self.conf([], 'routes'), 'redefine 3' - assert self.get()['status'] == 404, 'redefine request 3' +def test_routes_match_host_empty(): + route_match({"host": ""}) - assert 'success' in self.conf( - { - "listeners": {"*:7080": {"pass": "routes/main"}}, - "routes": {"main": [{"action": {"return": 200}}]}, - "applications": {}, - } - ), 'redefine 4' - assert self.get()['status'] == 200, 'redefine request 4' - - assert 'success' in self.conf_delete('routes/main/0'), 'redefine 5' - assert self.get()['status'] == 404, 'redefine request 5' - - assert 'success' in self.conf_post( - {"action": {"return": 200}}, 'routes/main' - ), 'redefine 6' - assert self.get()['status'] == 200, 'redefine request 6' - - assert 'error' in self.conf( - {"action": {"return": 200}}, 'routes/main/2' - ), 'redefine 7' - assert 'success' in self.conf( - {"action": {"return": 201}}, 'routes/main/1' - ), 'redefine 8' - - assert len(self.conf_get('routes/main')) == 2, 'redefine conf 8' - assert self.get()['status'] == 200, 'redefine request 8' - - def test_routes_edit(self): - self.route_match({"method": "GET"}) - - assert self.get()['status'] == 200, 'routes edit GET' - assert self.post()['status'] == 404, 'routes edit POST' - - assert 'success' in self.conf_post( - {"match": {"method": "POST"}, "action": {"return": 200}}, - 'routes', - ), 'routes edit configure 2' - assert 'GET' == self.conf_get( - 'routes/0/match/method' - ), 'routes edit configure 2 check' - assert 'POST' == self.conf_get( - 'routes/1/match/method' - ), 'routes edit configure 2 check 2' - - assert self.get()['status'] == 200, 'routes edit GET 2' - assert self.post()['status'] == 200, 'routes edit POST 2' - - assert 'success' in self.conf_delete( - 'routes/0' - ), 'routes edit configure 3' - - assert self.get()['status'] == 404, 'routes edit GET 3' - assert self.post()['status'] == 200, 'routes edit POST 3' - - assert 'error' in self.conf_delete( - 'routes/1' - ), 'routes edit configure invalid' - assert 'error' in self.conf_delete( - 'routes/-1' - ), 'routes edit configure invalid 2' - assert 'error' in self.conf_delete( - 'routes/blah' - ), 'routes edit configure invalid 3' - - assert self.get()['status'] == 404, 'routes edit GET 4' - assert self.post()['status'] == 200, 'routes edit POST 4' - - assert 'success' in self.conf_delete( - 'routes/0' - ), 'routes edit configure 5' - - assert self.get()['status'] == 404, 'routes edit GET 5' - assert self.post()['status'] == 404, 'routes edit POST 5' - - assert 'success' in self.conf_post( - {"match": {"method": "POST"}, "action": {"return": 200}}, - 'routes', - ), 'routes edit configure 6' - - assert self.get()['status'] == 404, 'routes edit GET 6' - assert self.post()['status'] == 200, 'routes edit POST 6' - - assert 'success' in self.conf( - { - "listeners": {"*:7080": {"pass": "routes/main"}}, - "routes": {"main": [{"action": {"return": 200}}]}, - "applications": {}, - } - ), 'route edit configure 7' - - assert 'error' in self.conf_delete( - 'routes/0' - ), 'routes edit configure invalid 4' - assert 'error' in self.conf_delete( - 'routes/main' - ), 'routes edit configure invalid 5' - - assert self.get()['status'] == 200, 'routes edit GET 7' - - assert 'success' in self.conf_delete( - 'listeners/*:7080' - ), 'route edit configure 8' - assert 'success' in self.conf_delete( - 'routes/main' - ), 'route edit configure 9' - - def test_match_edit(self, skip_alert): - skip_alert(r'failed to apply new conf') - - self.route_match({"method": ["GET", "POST"]}) - - assert self.get()['status'] == 200, 'match edit GET' - assert self.post()['status'] == 200, 'match edit POST' - assert self.put()['status'] == 404, 'match edit PUT' - - assert 'success' in self.conf_post( - '\"PUT\"', 'routes/0/match/method' - ), 'match edit configure 2' - assert ['GET', 'POST', 'PUT'] == self.conf_get( - 'routes/0/match/method' - ), 'match edit configure 2 check' - - assert self.get()['status'] == 200, 'match edit GET 2' - assert self.post()['status'] == 200, 'match edit POST 2' - assert self.put()['status'] == 200, 'match edit PUT 2' - - assert 'success' in self.conf_delete( - 'routes/0/match/method/1' - ), 'match edit configure 3' - assert ['GET', 'PUT'] == self.conf_get( - 'routes/0/match/method' - ), 'match edit configure 3 check' - - assert self.get()['status'] == 200, 'match edit GET 3' - assert self.post()['status'] == 404, 'match edit POST 3' - assert self.put()['status'] == 200, 'match edit PUT 3' - - assert 'success' in self.conf_delete( - 'routes/0/match/method/1' - ), 'match edit configure 4' - assert ['GET'] == self.conf_get( - 'routes/0/match/method' - ), 'match edit configure 4 check' - - assert self.get()['status'] == 200, 'match edit GET 4' - assert self.post()['status'] == 404, 'match edit POST 4' - assert self.put()['status'] == 404, 'match edit PUT 4' - - assert 'error' in self.conf_delete( - 'routes/0/match/method/1' - ), 'match edit configure invalid' - assert 'error' in self.conf_delete( - 'routes/0/match/method/-1' - ), 'match edit configure invalid 2' - assert 'error' in self.conf_delete( - 'routes/0/match/method/blah' - ), 'match edit configure invalid 3' - assert ['GET'] == self.conf_get( - 'routes/0/match/method' - ), 'match edit configure 5 check' - - assert self.get()['status'] == 200, 'match edit GET 5' - assert self.post()['status'] == 404, 'match edit POST 5' - assert self.put()['status'] == 404, 'match edit PUT 5' - - assert 'success' in self.conf_delete( - 'routes/0/match/method/0' - ), 'match edit configure 6' - assert [] == self.conf_get( - 'routes/0/match/method' - ), 'match edit configure 6 check' - - assert self.get()['status'] == 200, 'match edit GET 6' - assert self.post()['status'] == 200, 'match edit POST 6' - assert self.put()['status'] == 200, 'match edit PUT 6' - - assert 'success' in self.conf( - '"GET"', 'routes/0/match/method' - ), 'match edit configure 7' - - assert self.get()['status'] == 200, 'match edit GET 7' - assert self.post()['status'] == 404, 'match edit POST 7' - assert self.put()['status'] == 404, 'match edit PUT 7' - - assert 'error' in self.conf_delete( - 'routes/0/match/method/0' - ), 'match edit configure invalid 5' - assert 'error' in self.conf( - {}, 'routes/0/action' - ), 'match edit configure invalid 6' - - assert 'success' in self.conf( - {}, 'routes/0/match' - ), 'match edit configure 8' - - assert self.get()['status'] == 200, 'match edit GET 8' - - def test_routes_match_rules(self): - self.route_match({"method": "GET", "host": "localhost", "uri": "/"}) - - assert self.get()['status'] == 200, 'routes match rules' - - def test_routes_loop(self): - assert 'success' in self.route( - {"match": {"uri": "/"}, "action": {"pass": "routes"}} - ), 'routes loop configure' - - assert self.get()['status'] == 500, 'routes loop' - - def test_routes_match_headers(self): - self.route_match({"headers": {"host": "localhost"}}) - - assert self.get()['status'] == 200, 'match headers' - self.host('Localhost', 200) - self.host('localhost.com', 404) - self.host('llocalhost', 404) - self.host('host', 404) - - def test_routes_match_headers_multiple(self): - self.route_match({"headers": {"host": "localhost", "x-blah": "test"}}) - - assert self.get()['status'] == 404, 'match headers multiple' - assert ( - self.get( - headers={ - "Host": "localhost", - "X-blah": "test", - "Connection": "close", - } - )['status'] - == 200 - ), 'match headers multiple 2' + host('', 200) + assert ( + client.get(http_10=True, headers={})['status'] == 200 + ), 'match host empty 2' + assert client.get()['status'] == 404, 'match host empty 3' - assert ( - self.get( - headers={ - "Host": "localhost", - "X-blah": "", - "Connection": "close", - } - )['status'] - == 404 - ), 'match headers multiple 3' - def test_routes_match_headers_multiple_values(self): - self.route_match({"headers": {"x-blah": "test"}}) +def test_routes_match_uri_positive(): + route_match({"uri": ["/blah", "/slash/"]}) - assert ( - self.get( - headers={ - "Host": "localhost", - "X-blah": ["test", "test", "test"], - "Connection": "close", - } - )['status'] - == 200 - ), 'match headers multiple values' - assert ( - self.get( - headers={ - "Host": "localhost", - "X-blah": ["test", "blah", "test"], - "Connection": "close", - } - )['status'] - == 404 - ), 'match headers multiple values 2' - assert ( - self.get( - headers={ - "Host": "localhost", - "X-blah": ["test", "", "test"], - "Connection": "close", - } - )['status'] - == 404 - ), 'match headers multiple values 3' + assert client.get()['status'] == 404, '/' + assert client.get(url='/blah')['status'] == 200, '/blah' + assert client.get(url='/blah#foo')['status'] == 200, '/blah#foo' + assert client.get(url='/blah?var')['status'] == 200, '/blah?var' + assert client.get(url='//blah')['status'] == 200, '//blah' + assert client.get(url='/slash/foo/../')['status'] == 200, 'relative' + assert client.get(url='/slash/./')['status'] == 200, '/slash/./' + assert client.get(url='/slash//.//')['status'] == 200, 'adjacent slashes' + assert client.get(url='/%')['status'] == 400, 'percent' + assert client.get(url='/%1')['status'] == 400, 'percent digit' + assert client.get(url='/%A')['status'] == 400, 'percent letter' + assert client.get(url='/slash/.?args')['status'] == 200, 'dot args' + assert client.get(url='/slash/.#frag')['status'] == 200, 'dot frag' + assert client.get(url='/slash/foo/..?args')['status'] == 200, 'dot dot args' + assert client.get(url='/slash/foo/..#frag')['status'] == 200, 'dot dot frag' + assert client.get(url='/slash/.')['status'] == 200, 'trailing dot' + assert client.get(url='/slash/foo/..')['status'] == 200, 'trailing dot dot' - def test_routes_match_headers_multiple_rules(self): - self.route_match({"headers": {"x-blah": ["test", "blah"]}}) - assert self.get()['status'] == 404, 'match headers multiple rules' - assert ( - self.get( - headers={ - "Host": "localhost", - "X-blah": "test", - "Connection": "close", - } - )['status'] - == 200 - ), 'match headers multiple rules 2' - assert ( - self.get( - headers={ - "Host": "localhost", - "X-blah": "blah", - "Connection": "close", - } - )['status'] - == 200 - ), 'match headers multiple rules 3' - assert ( - self.get( - headers={ - "Host": "localhost", - "X-blah": ["test", "blah", "test"], - "Connection": "close", - } - )['status'] - == 200 - ), 'match headers multiple rules 4' +def test_routes_match_uri_case_sensitive(): + route_match({"uri": "/BLAH"}) - assert ( - self.get( - headers={ - "Host": "localhost", - "X-blah": ["blah", ""], - "Connection": "close", - } - )['status'] - == 404 - ), 'match headers multiple rules 5' + assert client.get(url='/blah')['status'] == 404, '/blah' + assert client.get(url='/BlaH')['status'] == 404, '/BlaH' + assert client.get(url='/BLAH')['status'] == 200, '/BLAH' - def test_routes_match_headers_case_insensitive(self): - self.route_match({"headers": {"X-BLAH": "TEST"}}) - assert ( - self.get( - headers={ - "Host": "localhost", - "x-blah": "test", - "Connection": "close", - } - )['status'] - == 200 - ), 'match headers case insensitive' +def test_routes_match_uri_normalize(): + route_match({"uri": "/blah"}) - def test_routes_match_headers_invalid(self): - self.route_match_invalid({"headers": ["blah"]}) - self.route_match_invalid({"headers": {"foo": ["bar", {}]}}) - self.route_match_invalid({"headers": {"": "blah"}}) + assert client.get(url='/%62%6c%61%68')['status'] == 200, 'normalize' - def test_routes_match_headers_empty_rule(self): - self.route_match({"headers": {"host": ""}}) - assert self.get()['status'] == 404, 'localhost' - self.host('', 200) +def test_routes_match_empty_array(): + route_match({"uri": []}) - def test_routes_match_headers_empty(self): - self.route_match({"headers": {}}) - assert self.get()['status'] == 200, 'empty' + assert client.get(url='/blah')['status'] == 200, 'empty array' - self.route_match({"headers": []}) - assert self.get()['status'] == 200, 'empty 2' - def test_routes_match_headers_rule_array_empty(self): - self.route_match({"headers": {"blah": []}}) +def test_routes_reconfigure(): + assert 'success' in client.conf([], 'routes'), 'redefine' + assert client.get()['status'] == 404, 'redefine request' - assert self.get()['status'] == 404, 'array empty' - assert ( - self.get( - headers={ - "Host": "localhost", - "blah": "foo", - "Connection": "close", - } - )['status'] - == 200 - ), 'match headers rule array empty 2' + assert 'success' in client.conf( + [{"action": {"return": 200}}], 'routes' + ), 'redefine 2' + assert client.get()['status'] == 200, 'redefine request 2' - def test_routes_match_headers_array(self): - self.route_match( - { - "headers": [ - {"x-header1": "foo*"}, - {"x-header2": "bar"}, - {"x-header3": ["foo", "bar"]}, - {"x-header1": "bar", "x-header4": "foo"}, - ] - } - ) + assert 'success' in client.conf([], 'routes'), 'redefine 3' + assert client.get()['status'] == 404, 'redefine request 3' - def check_headers(hds): - hds = dict({"Host": "localhost", "Connection": "close"}, **hds) - assert self.get(headers=hds)['status'] == 200, 'headers array match' - - def check_headers_404(hds): - hds = dict({"Host": "localhost", "Connection": "close"}, **hds) - assert ( - self.get(headers=hds)['status'] == 404 - ), 'headers array no match' - - assert self.get()['status'] == 404, 'match headers array' - check_headers({"x-header1": "foo123"}) - check_headers({"x-header2": "bar"}) - check_headers({"x-header3": "bar"}) - check_headers_404({"x-header1": "bar"}) - check_headers({"x-header1": "bar", "x-header4": "foo"}) - - assert 'success' in self.conf_delete( - 'routes/0/match/headers/1' - ), 'match headers array configure 2' - - check_headers_404({"x-header2": "bar"}) - check_headers({"x-header3": "foo"}) - - def test_routes_match_arguments(self): - self.route_match({"arguments": {"foo": "bar"}}) - - assert self.get()['status'] == 404, 'args' - assert self.get(url='/?foo=bar')['status'] == 200, 'args 2' - assert self.get(url='/?foo=bar1')['status'] == 404, 'args 3' - assert self.get(url='/?1foo=bar')['status'] == 404, 'args 4' - assert self.get(url='/?Foo=bar')['status'] == 404, 'case' - assert self.get(url='/?foo=Bar')['status'] == 404, 'case 2' - - def test_routes_match_arguments_chars(self): - chars = ( - " !\"%23$%25%26'()*%2B,-./0123456789:;<%3D>?@" - "ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~" - ) + assert 'success' in client.conf( + { + "listeners": {"*:7080": {"pass": "routes/main"}}, + "routes": {"main": [{"action": {"return": 200}}]}, + "applications": {}, + } + ), 'redefine 4' + assert client.get()['status'] == 200, 'redefine request 4' - chars_enc = "" - for h1 in ["2", "3", "4", "5", "6", "7"]: - for h2 in [ - "0", - "1", - "2", - "3", - "4", - "5", - "6", - "7", - "8", - "9", - "A", - "B", - "C", - "D", - "E", - "F", - ]: - chars_enc += f'%{h1}{h2}' - chars_enc = chars_enc[:-3] - - def check_args(args, query): - self.route_match({"arguments": args}) - assert self.get(url=f'/?{query}')['status'] == 200 - - check_args({chars: chars}, f'{chars}={chars}') - check_args({chars: chars}, f'{chars}={chars_enc}') - check_args({chars: chars}, f'{chars_enc}={chars}') - check_args({chars: chars}, f'{chars_enc}={chars_enc}') - check_args({chars_enc: chars_enc}, f'{chars}={chars}') - check_args({chars_enc: chars_enc}, f'{chars}={chars_enc}') - check_args({chars_enc: chars_enc}, f'{chars_enc}={chars}') - check_args({chars_enc: chars_enc}, f'{chars_enc}={chars_enc}') - - def test_routes_match_arguments_empty(self): - self.route_match({"arguments": {}}) - assert self.get()['status'] == 200, 'arguments empty' - - self.route_match({"arguments": []}) - assert self.get()['status'] == 200, 'arguments empty 2' - - def test_routes_match_arguments_space(self): - self.route_match({"arguments": {"+fo o%20": "%20b+a r"}}) - assert self.get(url='/? fo o = b a r&')['status'] == 200 - assert self.get(url='/?+fo+o+=+b+a+r&')['status'] == 200 - assert self.get(url='/?%20fo%20o%20=%20b%20a%20r&')['status'] == 200 - - self.route_match({"arguments": {"%20foo": " bar"}}) - assert self.get(url='/? foo= bar')['status'] == 200 - assert self.get(url='/?+foo=+bar')['status'] == 200 - assert self.get(url='/?%20foo=%20bar')['status'] == 200 - assert self.get(url='/?+foo= bar')['status'] == 200 - assert self.get(url='/?%20foo=+bar')['status'] == 200 - - def test_routes_match_arguments_equal(self): - self.route_match({"arguments": {"=": "="}}) - assert self.get(url='/?%3D=%3D')['status'] == 200 - assert self.get(url='/?%3D==')['status'] == 200 - assert self.get(url='/?===')['status'] == 404 - assert self.get(url='/?%3D%3D%3D')['status'] == 404 - assert self.get(url='/?==%3D')['status'] == 404 - - def test_routes_match_arguments_enc(self): - self.route_match({"arguments": {"Ю": "н"}}) - assert self.get(url='/?%D0%AE=%D0%BD')['status'] == 200 - assert self.get(url='/?%d0%ae=%d0%Bd')['status'] == 200 - - def test_routes_match_arguments_hash(self): - self.route_match({"arguments": {"#": "#"}}) - assert self.get(url='/?%23=%23')['status'] == 200 - assert self.get(url='/?%23=%23#')['status'] == 200 - assert self.get(url='/?#=#')['status'] == 404 - assert self.get(url='/?%23=#')['status'] == 404 - - def test_routes_match_arguments_wildcard(self): - self.route_match({"arguments": {"foo": "*"}}) - assert self.get(url='/?foo')['status'] == 200 - assert self.get(url='/?foo=')['status'] == 200 - assert self.get(url='/?foo=blah')['status'] == 200 - assert self.get(url='/?blah=foo')['status'] == 404 - - self.route_match({"arguments": {"foo": "%25*"}}) - assert self.get(url='/?foo=%xx')['status'] == 200 - - self.route_match({"arguments": {"foo": "%2A*"}}) - assert self.get(url='/?foo=*xx')['status'] == 200 - assert self.get(url='/?foo=xx')['status'] == 404 - - self.route_match({"arguments": {"foo": "*%2A"}}) - assert self.get(url='/?foo=xx*')['status'] == 200 - assert self.get(url='/?foo=xx*x')['status'] == 404 - - self.route_match({"arguments": {"foo": "1*2"}}) - assert self.get(url='/?foo=12')['status'] == 200 - assert self.get(url='/?foo=1blah2')['status'] == 200 - assert self.get(url='/?foo=1%2A2')['status'] == 200 - assert self.get(url='/?foo=x12')['status'] == 404 - - self.route_match({"arguments": {"foo": "bar*", "%25": "%25"}}) - assert self.get(url='/?foo=barxx&%=%')['status'] == 200 - assert self.get(url='/?foo=barxx&x%=%')['status'] == 404 - - def test_routes_match_arguments_negative(self): - self.route_match({"arguments": {"foo": "!"}}) - assert self.get(url='/?bar')['status'] == 404 - assert self.get(url='/?foo')['status'] == 404 - assert self.get(url='/?foo=')['status'] == 404 - assert self.get(url='/?foo=%25')['status'] == 200 - - self.route_match({"arguments": {"foo": "!*"}}) - assert self.get(url='/?bar')['status'] == 404 - assert self.get(url='/?foo')['status'] == 404 - assert self.get(url='/?foo=')['status'] == 404 - assert self.get(url='/?foo=blah')['status'] == 404 - - self.route_match({"arguments": {"foo": "!%25"}}) - assert self.get(url='/?foo=blah')['status'] == 200 - assert self.get(url='/?foo=%')['status'] == 404 - - self.route_match({"arguments": {"foo": "%21blah"}}) - assert self.get(url='/?foo=%21blah')['status'] == 200 - assert self.get(url='/?foo=!blah')['status'] == 200 - assert self.get(url='/?foo=bar')['status'] == 404 - - self.route_match({"arguments": {"foo": "!!%21*a"}}) - assert self.get(url='/?foo=blah')['status'] == 200 - assert self.get(url='/?foo=!blah')['status'] == 200 - assert self.get(url='/?foo=!!a')['status'] == 404 - assert self.get(url='/?foo=!!bla')['status'] == 404 - - def test_routes_match_arguments_percent(self): - self.route_match({"arguments": {"%25": "%25"}}) - assert self.get(url='/?%=%')['status'] == 200 - assert self.get(url='/?%25=%25')['status'] == 200 - assert self.get(url='/?%25=%')['status'] == 200 - - self.route_match({"arguments": {"%251": "%252"}}) - assert self.get(url='/?%1=%2')['status'] == 200 - assert self.get(url='/?%251=%252')['status'] == 200 - assert self.get(url='/?%251=%2')['status'] == 200 - - self.route_match({"arguments": {"%25%21%251": "%25%24%252"}}) - assert self.get(url='/?%!%1=%$%2')['status'] == 200 - assert self.get(url='/?%25!%251=%25$%252')['status'] == 200 - assert self.get(url='/?%25!%1=%$%2')['status'] == 200 - - def test_routes_match_arguments_ampersand(self): - self.route_match({"arguments": {"foo": "&"}}) - assert self.get(url='/?foo=%26')['status'] == 200 - assert self.get(url='/?foo=%26&')['status'] == 200 - assert self.get(url='/?foo=%26%26')['status'] == 404 - assert self.get(url='/?foo=&')['status'] == 404 - - self.route_match({"arguments": {"&": ""}}) - assert self.get(url='/?%26=')['status'] == 200 - assert self.get(url='/?%26=&')['status'] == 200 - assert self.get(url='/?%26=%26')['status'] == 404 - assert self.get(url='/?&=')['status'] == 404 - - def test_routes_match_arguments_complex(self): - self.route_match({"arguments": {"foo": ""}}) - - assert self.get(url='/?foo')['status'] == 200, 'complex' - assert self.get(url='/?blah=blah&foo=')['status'] == 200, 'complex 2' - assert self.get(url='/?&&&foo&&&')['status'] == 200, 'complex 3' - assert self.get(url='/?foo&foo=bar&foo')['status'] == 404, 'complex 4' - assert self.get(url='/?foo=&foo')['status'] == 200, 'complex 5' - assert self.get(url='/?&=&foo&==&')['status'] == 200, 'complex 6' - assert self.get(url='/?&=&bar&==&')['status'] == 404, 'complex 7' - - def test_routes_match_arguments_multiple(self): - self.route_match({"arguments": {"foo": "bar", "blah": "test"}}) - - assert self.get()['status'] == 404, 'multiple' - assert ( - self.get(url='/?foo=bar&blah=test')['status'] == 200 - ), 'multiple 2' - assert self.get(url='/?foo=bar&blah')['status'] == 404, 'multiple 3' - assert self.get(url='/?foo=bar&blah=tes')['status'] == 404, 'multiple 4' - assert ( - self.get(url='/?foo=b%61r&bl%61h=t%65st')['status'] == 200 - ), 'multiple 5' + assert 'success' in client.conf_delete('routes/main/0'), 'redefine 5' + assert client.get()['status'] == 404, 'redefine request 5' - def test_routes_match_arguments_multiple_rules(self): - self.route_match({"arguments": {"foo": ["bar", "blah"]}}) + assert 'success' in client.conf_post( + {"action": {"return": 200}}, 'routes/main' + ), 'redefine 6' + assert client.get()['status'] == 200, 'redefine request 6' - assert self.get()['status'] == 404, 'rules' - assert self.get(url='/?foo=bar')['status'] == 200, 'rules 2' - assert self.get(url='/?foo=blah')['status'] == 200, 'rules 3' - assert ( - self.get(url='/?foo=blah&foo=bar&foo=blah')['status'] == 200 - ), 'rules 4' - assert ( - self.get(url='/?foo=blah&foo=bar&foo=')['status'] == 404 - ), 'rules 5' + assert 'error' in client.conf( + {"action": {"return": 200}}, 'routes/main/2' + ), 'redefine 7' + assert 'success' in client.conf( + {"action": {"return": 201}}, 'routes/main/1' + ), 'redefine 8' - def test_routes_match_arguments_array(self): - self.route_match( - { - "arguments": [ - {"var1": "val1*"}, - {"var2": "val2"}, - {"var3": ["foo", "bar"]}, - {"var1": "bar", "var4": "foo"}, - ] + assert len(client.conf_get('routes/main')) == 2, 'redefine conf 8' + assert client.get()['status'] == 200, 'redefine request 8' + + +def test_routes_edit(): + route_match({"method": "GET"}) + + assert client.get()['status'] == 200, 'routes edit GET' + assert client.post()['status'] == 404, 'routes edit POST' + + assert 'success' in client.conf_post( + {"match": {"method": "POST"}, "action": {"return": 200}}, + 'routes', + ), 'routes edit configure 2' + assert 'GET' == client.conf_get( + 'routes/0/match/method' + ), 'routes edit configure 2 check' + assert 'POST' == client.conf_get( + 'routes/1/match/method' + ), 'routes edit configure 2 check 2' + + assert client.get()['status'] == 200, 'routes edit GET 2' + assert client.post()['status'] == 200, 'routes edit POST 2' + + assert 'success' in client.conf_delete( + 'routes/0' + ), 'routes edit configure 3' + + assert client.get()['status'] == 404, 'routes edit GET 3' + assert client.post()['status'] == 200, 'routes edit POST 3' + + assert 'error' in client.conf_delete( + 'routes/1' + ), 'routes edit configure invalid' + assert 'error' in client.conf_delete( + 'routes/-1' + ), 'routes edit configure invalid 2' + assert 'error' in client.conf_delete( + 'routes/blah' + ), 'routes edit configure invalid 3' + + assert client.get()['status'] == 404, 'routes edit GET 4' + assert client.post()['status'] == 200, 'routes edit POST 4' + + assert 'success' in client.conf_delete( + 'routes/0' + ), 'routes edit configure 5' + + assert client.get()['status'] == 404, 'routes edit GET 5' + assert client.post()['status'] == 404, 'routes edit POST 5' + + assert 'success' in client.conf_post( + {"match": {"method": "POST"}, "action": {"return": 200}}, + 'routes', + ), 'routes edit configure 6' + + assert client.get()['status'] == 404, 'routes edit GET 6' + assert client.post()['status'] == 200, 'routes edit POST 6' + + assert 'success' in client.conf( + { + "listeners": {"*:7080": {"pass": "routes/main"}}, + "routes": {"main": [{"action": {"return": 200}}]}, + "applications": {}, + } + ), 'route edit configure 7' + + assert 'error' in client.conf_delete( + 'routes/0' + ), 'routes edit configure invalid 4' + assert 'error' in client.conf_delete( + 'routes/main' + ), 'routes edit configure invalid 5' + + assert client.get()['status'] == 200, 'routes edit GET 7' + + assert 'success' in client.conf_delete( + 'listeners/*:7080' + ), 'route edit configure 8' + assert 'success' in client.conf_delete( + 'routes/main' + ), 'route edit configure 9' + + +def test_match_edit(skip_alert): + skip_alert(r'failed to apply new conf') + + route_match({"method": ["GET", "POST"]}) + + assert client.get()['status'] == 200, 'match edit GET' + assert client.post()['status'] == 200, 'match edit POST' + assert client.put()['status'] == 404, 'match edit PUT' + + assert 'success' in client.conf_post( + '\"PUT\"', 'routes/0/match/method' + ), 'match edit configure 2' + assert ['GET', 'POST', 'PUT'] == client.conf_get( + 'routes/0/match/method' + ), 'match edit configure 2 check' + + assert client.get()['status'] == 200, 'match edit GET 2' + assert client.post()['status'] == 200, 'match edit POST 2' + assert client.put()['status'] == 200, 'match edit PUT 2' + + assert 'success' in client.conf_delete( + 'routes/0/match/method/1' + ), 'match edit configure 3' + assert ['GET', 'PUT'] == client.conf_get( + 'routes/0/match/method' + ), 'match edit configure 3 check' + + assert client.get()['status'] == 200, 'match edit GET 3' + assert client.post()['status'] == 404, 'match edit POST 3' + assert client.put()['status'] == 200, 'match edit PUT 3' + + assert 'success' in client.conf_delete( + 'routes/0/match/method/1' + ), 'match edit configure 4' + assert ['GET'] == client.conf_get( + 'routes/0/match/method' + ), 'match edit configure 4 check' + + assert client.get()['status'] == 200, 'match edit GET 4' + assert client.post()['status'] == 404, 'match edit POST 4' + assert client.put()['status'] == 404, 'match edit PUT 4' + + assert 'error' in client.conf_delete( + 'routes/0/match/method/1' + ), 'match edit configure invalid' + assert 'error' in client.conf_delete( + 'routes/0/match/method/-1' + ), 'match edit configure invalid 2' + assert 'error' in client.conf_delete( + 'routes/0/match/method/blah' + ), 'match edit configure invalid 3' + assert ['GET'] == client.conf_get( + 'routes/0/match/method' + ), 'match edit configure 5 check' + + assert client.get()['status'] == 200, 'match edit GET 5' + assert client.post()['status'] == 404, 'match edit POST 5' + assert client.put()['status'] == 404, 'match edit PUT 5' + + assert 'success' in client.conf_delete( + 'routes/0/match/method/0' + ), 'match edit configure 6' + assert [] == client.conf_get( + 'routes/0/match/method' + ), 'match edit configure 6 check' + + assert client.get()['status'] == 200, 'match edit GET 6' + assert client.post()['status'] == 200, 'match edit POST 6' + assert client.put()['status'] == 200, 'match edit PUT 6' + + assert 'success' in client.conf( + '"GET"', 'routes/0/match/method' + ), 'match edit configure 7' + + assert client.get()['status'] == 200, 'match edit GET 7' + assert client.post()['status'] == 404, 'match edit POST 7' + assert client.put()['status'] == 404, 'match edit PUT 7' + + assert 'error' in client.conf_delete( + 'routes/0/match/method/0' + ), 'match edit configure invalid 5' + assert 'error' in client.conf( + {}, 'routes/0/action' + ), 'match edit configure invalid 6' + + assert 'success' in client.conf( + {}, 'routes/0/match' + ), 'match edit configure 8' + + assert client.get()['status'] == 200, 'match edit GET 8' + + +def test_routes_match_rules(): + route_match({"method": "GET", "host": "localhost", "uri": "/"}) + + assert client.get()['status'] == 200, 'routes match rules' + + +def test_routes_loop(): + assert 'success' in route( + {"match": {"uri": "/"}, "action": {"pass": "routes"}} + ), 'routes loop configure' + + assert client.get()['status'] == 500, 'routes loop' + + +def test_routes_match_headers(): + route_match({"headers": {"host": "localhost"}}) + + assert client.get()['status'] == 200, 'match headers' + host('Localhost', 200) + host('localhost.com', 404) + host('llocalhost', 404) + host('host', 404) + + +def test_routes_match_headers_multiple(): + route_match({"headers": {"host": "localhost", "x-blah": "test"}}) + + assert client.get()['status'] == 404, 'match headers multiple' + assert ( + client.get( + headers={ + "Host": "localhost", + "X-blah": "test", + "Connection": "close", } - ) + )['status'] + == 200 + ), 'match headers multiple 2' + + assert ( + client.get( + headers={ + "Host": "localhost", + "X-blah": "", + "Connection": "close", + } + )['status'] + == 404 + ), 'match headers multiple 3' - assert self.get()['status'] == 404, 'arr' - assert self.get(url='/?var1=val123')['status'] == 200, 'arr 2' - assert self.get(url='/?var2=val2')['status'] == 200, 'arr 3' - assert self.get(url='/?var3=bar')['status'] == 200, 'arr 4' - assert self.get(url='/?var1=bar')['status'] == 404, 'arr 5' - assert self.get(url='/?var1=bar&var4=foo')['status'] == 200, 'arr 6' - - assert 'success' in self.conf_delete( - 'routes/0/match/arguments/1' - ), 'match arguments array configure 2' - - assert self.get(url='/?var2=val2')['status'] == 404, 'arr 7' - assert self.get(url='/?var3=foo')['status'] == 200, 'arr 8' - - def test_routes_match_arguments_invalid(self): - self.route_match_invalid({"arguments": ["var"]}) - self.route_match_invalid({"arguments": [{"var1": {}}]}) - self.route_match_invalid({"arguments": {"": "bar"}}) - self.route_match_invalid({"arguments": {"foo": "%"}}) - self.route_match_invalid({"arguments": {"foo": "%1G"}}) - self.route_match_invalid({"arguments": {"%": "bar"}}) - self.route_match_invalid({"arguments": {"foo": "%0"}}) - self.route_match_invalid({"arguments": {"foo": "%%1F"}}) - self.route_match_invalid({"arguments": {"%%1F": ""}}) - self.route_match_invalid({"arguments": {"%7%F": ""}}) - - def test_routes_match_query(self): - self.route_match({"query": "!"}) - assert self.get(url='/')['status'] == 404 - assert self.get(url='/?')['status'] == 404 - assert self.get(url='/?foo')['status'] == 200 - assert self.get(url='/?foo=')['status'] == 200 - assert self.get(url='/?foo=baz')['status'] == 200 - - self.route_match({"query": "foo=%26"}) - assert self.get(url='/?foo=&')['status'] == 200 - - self.route_match({"query": "a=b&c=d"}) - assert self.get(url='/?a=b&c=d')['status'] == 200 - - self.route_match({"query": "a=b%26c%3Dd"}) - assert self.get(url='/?a=b%26c%3Dd')['status'] == 200 - assert self.get(url='/?a=b&c=d')['status'] == 200 - - self.route_match({"query": "a=b%26c%3Dd+e"}) - assert self.get(url='/?a=b&c=d e')['status'] == 200 - - def test_routes_match_query_array(self): - self.route_match({"query": ["foo", "bar"]}) - - assert self.get()['status'] == 404, 'no args' - assert self.get(url='/?foo')['status'] == 200, 'arg first' - assert self.get(url='/?bar')['status'] == 200, 'arg second' - - assert 'success' in self.conf_delete( - 'routes/0/match/query/1' - ), 'query array remove second' - - assert self.get(url='/?foo')['status'] == 200, 'still arg first' - assert self.get(url='/?bar')['status'] == 404, 'no arg second' - - self.route_match({"query": ["!f", "foo"]}) - - assert self.get(url='/?f')['status'] == 404, 'negative arg' - assert self.get(url='/?fo')['status'] == 404, 'negative arg 2' - assert self.get(url='/?foo')['status'] == 200, 'negative arg 3' - - self.route_match({"query": []}) - assert self.get()['status'] == 200, 'empty array' - - def test_routes_match_query_invalid(self): - self.route_match_invalid({"query": [1]}) - self.route_match_invalid({"query": "%"}) - self.route_match_invalid({"query": "%1G"}) - self.route_match_invalid({"query": "%0"}) - self.route_match_invalid({"query": "%%1F"}) - self.route_match_invalid({"query": ["foo", "%3D", "%%1F"]}) - - def test_routes_match_cookies(self): - self.route_match({"cookies": {"foO": "bar"}}) - - assert self.get()['status'] == 404, 'cookie' - self.cookie('foO=bar', 200) - self.cookie('foO=bar;1', 200) - self.cookie(['foO=bar', 'blah=blah'], 200) - self.cookie('foO=bar; blah=blah', 200) - self.cookie('Foo=bar', 404) - self.cookie('foO=Bar', 404) - self.cookie('foO=bar1', 404) - self.cookie('1foO=bar;', 404) - - def test_routes_match_cookies_empty(self): - self.route_match({"cookies": {}}) - assert self.get()['status'] == 200, 'cookies empty' - - self.route_match({"cookies": []}) - assert self.get()['status'] == 200, 'cookies empty 2' - - def test_routes_match_cookies_invalid(self): - self.route_match_invalid({"cookies": ["var"]}) - self.route_match_invalid({"cookies": [{"foo": {}}]}) - - def test_routes_match_cookies_complex(self): - self.route_match({"cookies": {"foo": "bar=baz"}}) - self.cookie('foo=bar=baz', 200) - self.cookie(' foo=bar=baz ', 200) - self.cookie('=foo=bar=baz', 404) - - self.route_match({"cookies": {"foo": ""}}) - self.cookie('foo=', 200) - self.cookie('foo=;', 200) - self.cookie(' foo=;', 200) - self.cookie('foo', 404) - self.cookie('', 404) - self.cookie('=', 404) - - def test_routes_match_cookies_multiple(self): - self.route_match({"cookies": {"foo": "bar", "blah": "blah"}}) - - assert self.get()['status'] == 404, 'multiple' - self.cookie('foo=bar; blah=blah', 200) - self.cookie(['foo=bar', 'blah=blah'], 200) - self.cookie(['foo=bar; blah', 'blah'], 404) - self.cookie(['foo=bar; blah=test', 'blah=blah'], 404) - - def test_routes_match_cookies_multiple_values(self): - self.route_match({"cookies": {"blah": "blah"}}) - - self.cookie(['blah=blah', 'blah=blah', 'blah=blah'], 200) - self.cookie(['blah=blah', 'blah=test', 'blah=blah'], 404) - self.cookie(['blah=blah; blah=', 'blah=blah'], 404) - - def test_routes_match_cookies_multiple_rules(self): - self.route_match({"cookies": {"blah": ["test", "blah"]}}) - - assert self.get()['status'] == 404, 'multiple rules' - self.cookie('blah=test', 200) - self.cookie('blah=blah', 200) - self.cookie(['blah=blah', 'blah=test', 'blah=blah'], 200) - self.cookie(['blah=blah; blah=test', 'blah=blah'], 200) - self.cookie(['blah=blah', 'blah'], 200) # invalid cookie - - def test_routes_match_cookies_array(self): - self.route_match( - { - "cookies": [ - {"var1": "val1*"}, - {"var2": "val2"}, - {"var3": ["foo", "bar"]}, - {"var1": "bar", "var4": "foo"}, - ] + +def test_routes_match_headers_multiple_values(): + route_match({"headers": {"x-blah": "test"}}) + + assert ( + client.get( + headers={ + "Host": "localhost", + "X-blah": ["test", "test", "test"], + "Connection": "close", } - ) + )['status'] + == 200 + ), 'match headers multiple values' + assert ( + client.get( + headers={ + "Host": "localhost", + "X-blah": ["test", "blah", "test"], + "Connection": "close", + } + )['status'] + == 404 + ), 'match headers multiple values 2' + assert ( + client.get( + headers={ + "Host": "localhost", + "X-blah": ["test", "", "test"], + "Connection": "close", + } + )['status'] + == 404 + ), 'match headers multiple values 3' - assert self.get()['status'] == 404, 'cookies array' - self.cookie('var1=val123', 200) - self.cookie('var2=val2', 200) - self.cookie(' var2=val2 ', 200) - self.cookie('var3=bar', 200) - self.cookie('var3=bar;', 200) - self.cookie('var1=bar', 404) - self.cookie('var1=bar; var4=foo;', 200) - self.cookie(['var1=bar', 'var4=foo'], 200) - - assert 'success' in self.conf_delete( - 'routes/0/match/cookies/1' - ), 'match cookies array configure 2' - - self.cookie('var2=val2', 404) - self.cookie('var3=foo', 200) - - def test_routes_match_scheme(self): - self.route_match({"scheme": "http"}) - self.route_match({"scheme": "https"}) - self.route_match({"scheme": "HtTp"}) - self.route_match({"scheme": "HtTpS"}) - - def test_routes_match_scheme_invalid(self): - self.route_match_invalid({"scheme": ["http"]}) - self.route_match_invalid({"scheme": "ftp"}) - self.route_match_invalid({"scheme": "ws"}) - self.route_match_invalid({"scheme": "*"}) - self.route_match_invalid({"scheme": ""}) - - def test_routes_source_port(self): - def sock_port(): - sock = self.http(b'', raw=True, no_recv=True) - port = sock.getsockname()[1] - return (sock, port) - - sock, port = sock_port() - sock2, _ = sock_port() - - self.route_match({"source": f'127.0.0.1:{port}'}) - assert self.get(sock=sock)['status'] == 200, 'exact' - assert self.get(sock=sock2)['status'] == 404, 'exact 2' - - sock, port = sock_port() - sock2, _ = sock_port() - - self.route_match({"source": f'!127.0.0.1:{port}'}) - assert self.get(sock=sock)['status'] == 404, 'negative' - assert self.get(sock=sock2)['status'] == 200, 'negative 2' - - sock, port = sock_port() - sock2, _ = sock_port() - - self.route_match({"source": [f'*:{port}', "!127.0.0.1"]}) - assert self.get(sock=sock)['status'] == 404, 'negative 3' - assert self.get(sock=sock2)['status'] == 404, 'negative 4' - - sock, port = sock_port() - sock2, _ = sock_port() - - self.route_match({"source": f'127.0.0.1:{port}-{port}'}) - assert self.get(sock=sock)['status'] == 200, 'range single' - assert self.get(sock=sock2)['status'] == 404, 'range single 2' - - socks = [ - sock_port(), - sock_port(), - sock_port(), - sock_port(), - sock_port(), - ] - socks.sort(key=lambda sock: sock[1]) - - self.route_match({"source": f'127.0.0.1:{socks[1][1]}-{socks[3][1]}'}) - assert self.get(sock=socks[0][0])['status'] == 404, 'range' - assert self.get(sock=socks[1][0])['status'] == 200, 'range 2' - assert self.get(sock=socks[2][0])['status'] == 200, 'range 3' - assert self.get(sock=socks[3][0])['status'] == 200, 'range 4' - assert self.get(sock=socks[4][0])['status'] == 404, 'range 5' - - socks = [ - sock_port(), - sock_port(), - sock_port(), - ] - socks.sort(key=lambda sock: sock[1]) - - self.route_match( - { - "source": [ - f'127.0.0.1:{socks[0][1]}', - f'127.0.0.1:{socks[2][1]}', - ] + +def test_routes_match_headers_multiple_rules(): + route_match({"headers": {"x-blah": ["test", "blah"]}}) + + assert client.get()['status'] == 404, 'match headers multiple rules' + assert ( + client.get( + headers={ + "Host": "localhost", + "X-blah": "test", + "Connection": "close", } - ) - assert self.get(sock=socks[0][0])['status'] == 200, 'array' - assert self.get(sock=socks[1][0])['status'] == 404, 'array 2' - assert self.get(sock=socks[2][0])['status'] == 200, 'array 3' + )['status'] + == 200 + ), 'match headers multiple rules 2' + assert ( + client.get( + headers={ + "Host": "localhost", + "X-blah": "blah", + "Connection": "close", + } + )['status'] + == 200 + ), 'match headers multiple rules 3' + assert ( + client.get( + headers={ + "Host": "localhost", + "X-blah": ["test", "blah", "test"], + "Connection": "close", + } + )['status'] + == 200 + ), 'match headers multiple rules 4' + + assert ( + client.get( + headers={ + "Host": "localhost", + "X-blah": ["blah", ""], + "Connection": "close", + } + )['status'] + == 404 + ), 'match headers multiple rules 5' - def test_routes_source_addr(self): - assert 'success' in self.conf( - { - "*:7080": {"pass": "routes"}, - "[::1]:7081": {"pass": "routes"}, - }, - 'listeners', - ), 'source listeners configure' - def get_ipv6(): - return self.get(sock_type='ipv6', port=7081) +def test_routes_match_headers_case_insensitive(): + route_match({"headers": {"X-BLAH": "TEST"}}) - self.route_match({"source": "127.0.0.1"}) - assert self.get()['status'] == 200, 'exact' - assert get_ipv6()['status'] == 404, 'exact ipv6' + assert ( + client.get( + headers={ + "Host": "localhost", + "x-blah": "test", + "Connection": "close", + } + )['status'] + == 200 + ), 'match headers case insensitive' - self.route_match({"source": ["127.0.0.1"]}) - assert self.get()['status'] == 200, 'exact 2' - assert get_ipv6()['status'] == 404, 'exact 2 ipv6' - self.route_match({"source": "!127.0.0.1"}) - assert self.get()['status'] == 404, 'exact neg' - assert get_ipv6()['status'] == 200, 'exact neg ipv6' +def test_routes_match_headers_invalid(): + route_match_invalid({"headers": ["blah"]}) + route_match_invalid({"headers": {"foo": ["bar", {}]}}) + route_match_invalid({"headers": {"": "blah"}}) - self.route_match({"source": "127.0.0.2"}) - assert self.get()['status'] == 404, 'exact 3' - assert get_ipv6()['status'] == 404, 'exact 3 ipv6' - self.route_match({"source": "127.0.0.1-127.0.0.1"}) - assert self.get()['status'] == 200, 'range single' - assert get_ipv6()['status'] == 404, 'range single ipv6' +def test_routes_match_headers_empty_rule(): + route_match({"headers": {"host": ""}}) - self.route_match({"source": "127.0.0.2-127.0.0.2"}) - assert self.get()['status'] == 404, 'range single 2' - assert get_ipv6()['status'] == 404, 'range single 2 ipv6' + assert client.get()['status'] == 404, 'localhost' + host('', 200) - self.route_match({"source": "127.0.0.2-127.0.0.3"}) - assert self.get()['status'] == 404, 'range' - assert get_ipv6()['status'] == 404, 'range ipv6' - self.route_match({"source": "127.0.0.1-127.0.0.2"}) - assert self.get()['status'] == 200, 'range 2' - assert get_ipv6()['status'] == 404, 'range 2 ipv6' +def test_routes_match_headers_empty(): + route_match({"headers": {}}) + assert client.get()['status'] == 200, 'empty' - self.route_match({"source": "127.0.0.0-127.0.0.2"}) - assert self.get()['status'] == 200, 'range 3' - assert get_ipv6()['status'] == 404, 'range 3 ipv6' + route_match({"headers": []}) + assert client.get()['status'] == 200, 'empty 2' - self.route_match({"source": "127.0.0.0-127.0.0.1"}) - assert self.get()['status'] == 200, 'range 4' - assert get_ipv6()['status'] == 404, 'range 4 ipv6' - self.route_match({"source": "126.0.0.0-127.0.0.0"}) - assert self.get()['status'] == 404, 'range 5' - assert get_ipv6()['status'] == 404, 'range 5 ipv6' +def test_routes_match_headers_rule_array_empty(): + route_match({"headers": {"blah": []}}) - self.route_match({"source": "126.126.126.126-127.0.0.2"}) - assert self.get()['status'] == 200, 'range 6' - assert get_ipv6()['status'] == 404, 'range 6 ipv6' + assert client.get()['status'] == 404, 'array empty' + assert ( + client.get( + headers={ + "Host": "localhost", + "blah": "foo", + "Connection": "close", + } + )['status'] + == 200 + ), 'match headers rule array empty 2' + + +def test_routes_match_headers_array(): + route_match( + { + "headers": [ + {"x-header1": "foo*"}, + {"x-header2": "bar"}, + {"x-header3": ["foo", "bar"]}, + {"x-header1": "bar", "x-header4": "foo"}, + ] + } + ) + + def check_headers(hds): + hds = dict({"Host": "localhost", "Connection": "close"}, **hds) + assert client.get(headers=hds)['status'] == 200, 'headers array match' + + def check_headers_404(hds): + hds = dict({"Host": "localhost", "Connection": "close"}, **hds) + assert ( + client.get(headers=hds)['status'] == 404 + ), 'headers array no match' + + assert client.get()['status'] == 404, 'match headers array' + check_headers({"x-header1": "foo123"}) + check_headers({"x-header2": "bar"}) + check_headers({"x-header3": "bar"}) + check_headers_404({"x-header1": "bar"}) + check_headers({"x-header1": "bar", "x-header4": "foo"}) + + assert 'success' in client.conf_delete( + 'routes/0/match/headers/1' + ), 'match headers array configure 2' + + check_headers_404({"x-header2": "bar"}) + check_headers({"x-header3": "foo"}) + + +def test_routes_match_arguments(): + route_match({"arguments": {"foo": "bar"}}) + + assert client.get()['status'] == 404, 'args' + assert client.get(url='/?foo=bar')['status'] == 200, 'args 2' + assert client.get(url='/?foo=bar1')['status'] == 404, 'args 3' + assert client.get(url='/?1foo=bar')['status'] == 404, 'args 4' + assert client.get(url='/?Foo=bar')['status'] == 404, 'case' + assert client.get(url='/?foo=Bar')['status'] == 404, 'case 2' + + +def test_routes_match_arguments_chars(): + chars = ( + " !\"%23$%25%26'()*%2B,-./0123456789:;<%3D>?@" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~" + ) + + chars_enc = "" + for h1 in ["2", "3", "4", "5", "6", "7"]: + for h2 in [ + "0", + "1", + "2", + "3", + "4", + "5", + "6", + "7", + "8", + "9", + "A", + "B", + "C", + "D", + "E", + "F", + ]: + chars_enc += f'%{h1}{h2}' + chars_enc = chars_enc[:-3] + + def check_args(args, query): + route_match({"arguments": args}) + assert client.get(url=f'/?{query}')['status'] == 200 + + check_args({chars: chars}, f'{chars}={chars}') + check_args({chars: chars}, f'{chars}={chars_enc}') + check_args({chars: chars}, f'{chars_enc}={chars}') + check_args({chars: chars}, f'{chars_enc}={chars_enc}') + check_args({chars_enc: chars_enc}, f'{chars}={chars}') + check_args({chars_enc: chars_enc}, f'{chars}={chars_enc}') + check_args({chars_enc: chars_enc}, f'{chars_enc}={chars}') + check_args({chars_enc: chars_enc}, f'{chars_enc}={chars_enc}') + + +def test_routes_match_arguments_empty(): + route_match({"arguments": {}}) + assert client.get()['status'] == 200, 'arguments empty' + + route_match({"arguments": []}) + assert client.get()['status'] == 200, 'arguments empty 2' + + +def test_routes_match_arguments_space(): + route_match({"arguments": {"+fo o%20": "%20b+a r"}}) + assert client.get(url='/? fo o = b a r&')['status'] == 200 + assert client.get(url='/?+fo+o+=+b+a+r&')['status'] == 200 + assert client.get(url='/?%20fo%20o%20=%20b%20a%20r&')['status'] == 200 + + route_match({"arguments": {"%20foo": " bar"}}) + assert client.get(url='/? foo= bar')['status'] == 200 + assert client.get(url='/?+foo=+bar')['status'] == 200 + assert client.get(url='/?%20foo=%20bar')['status'] == 200 + assert client.get(url='/?+foo= bar')['status'] == 200 + assert client.get(url='/?%20foo=+bar')['status'] == 200 + + +def test_routes_match_arguments_equal(): + route_match({"arguments": {"=": "="}}) + assert client.get(url='/?%3D=%3D')['status'] == 200 + assert client.get(url='/?%3D==')['status'] == 200 + assert client.get(url='/?===')['status'] == 404 + assert client.get(url='/?%3D%3D%3D')['status'] == 404 + assert client.get(url='/?==%3D')['status'] == 404 + + +def test_routes_match_arguments_enc(): + route_match({"arguments": {"Ю": "н"}}) + assert client.get(url='/?%D0%AE=%D0%BD')['status'] == 200 + assert client.get(url='/?%d0%ae=%d0%Bd')['status'] == 200 + + +def test_routes_match_arguments_hash(): + route_match({"arguments": {"#": "#"}}) + assert client.get(url='/?%23=%23')['status'] == 200 + assert client.get(url='/?%23=%23#')['status'] == 200 + assert client.get(url='/?#=#')['status'] == 404 + assert client.get(url='/?%23=#')['status'] == 404 + + +def test_routes_match_arguments_wildcard(): + route_match({"arguments": {"foo": "*"}}) + assert client.get(url='/?foo')['status'] == 200 + assert client.get(url='/?foo=')['status'] == 200 + assert client.get(url='/?foo=blah')['status'] == 200 + assert client.get(url='/?blah=foo')['status'] == 404 + + route_match({"arguments": {"foo": "%25*"}}) + assert client.get(url='/?foo=%xx')['status'] == 200 + + route_match({"arguments": {"foo": "%2A*"}}) + assert client.get(url='/?foo=*xx')['status'] == 200 + assert client.get(url='/?foo=xx')['status'] == 404 + + route_match({"arguments": {"foo": "*%2A"}}) + assert client.get(url='/?foo=xx*')['status'] == 200 + assert client.get(url='/?foo=xx*x')['status'] == 404 + + route_match({"arguments": {"foo": "1*2"}}) + assert client.get(url='/?foo=12')['status'] == 200 + assert client.get(url='/?foo=1blah2')['status'] == 200 + assert client.get(url='/?foo=1%2A2')['status'] == 200 + assert client.get(url='/?foo=x12')['status'] == 404 + + route_match({"arguments": {"foo": "bar*", "%25": "%25"}}) + assert client.get(url='/?foo=barxx&%=%')['status'] == 200 + assert client.get(url='/?foo=barxx&x%=%')['status'] == 404 + + +def test_routes_match_arguments_negative(): + route_match({"arguments": {"foo": "!"}}) + assert client.get(url='/?bar')['status'] == 404 + assert client.get(url='/?foo')['status'] == 404 + assert client.get(url='/?foo=')['status'] == 404 + assert client.get(url='/?foo=%25')['status'] == 200 + + route_match({"arguments": {"foo": "!*"}}) + assert client.get(url='/?bar')['status'] == 404 + assert client.get(url='/?foo')['status'] == 404 + assert client.get(url='/?foo=')['status'] == 404 + assert client.get(url='/?foo=blah')['status'] == 404 + + route_match({"arguments": {"foo": "!%25"}}) + assert client.get(url='/?foo=blah')['status'] == 200 + assert client.get(url='/?foo=%')['status'] == 404 + + route_match({"arguments": {"foo": "%21blah"}}) + assert client.get(url='/?foo=%21blah')['status'] == 200 + assert client.get(url='/?foo=!blah')['status'] == 200 + assert client.get(url='/?foo=bar')['status'] == 404 + + route_match({"arguments": {"foo": "!!%21*a"}}) + assert client.get(url='/?foo=blah')['status'] == 200 + assert client.get(url='/?foo=!blah')['status'] == 200 + assert client.get(url='/?foo=!!a')['status'] == 404 + assert client.get(url='/?foo=!!bla')['status'] == 404 + + +def test_routes_match_arguments_percent(): + route_match({"arguments": {"%25": "%25"}}) + assert client.get(url='/?%=%')['status'] == 200 + assert client.get(url='/?%25=%25')['status'] == 200 + assert client.get(url='/?%25=%')['status'] == 200 + + route_match({"arguments": {"%251": "%252"}}) + assert client.get(url='/?%1=%2')['status'] == 200 + assert client.get(url='/?%251=%252')['status'] == 200 + assert client.get(url='/?%251=%2')['status'] == 200 + + route_match({"arguments": {"%25%21%251": "%25%24%252"}}) + assert client.get(url='/?%!%1=%$%2')['status'] == 200 + assert client.get(url='/?%25!%251=%25$%252')['status'] == 200 + assert client.get(url='/?%25!%1=%$%2')['status'] == 200 + + +def test_routes_match_arguments_ampersand(): + route_match({"arguments": {"foo": "&"}}) + assert client.get(url='/?foo=%26')['status'] == 200 + assert client.get(url='/?foo=%26&')['status'] == 200 + assert client.get(url='/?foo=%26%26')['status'] == 404 + assert client.get(url='/?foo=&')['status'] == 404 + + route_match({"arguments": {"&": ""}}) + assert client.get(url='/?%26=')['status'] == 200 + assert client.get(url='/?%26=&')['status'] == 200 + assert client.get(url='/?%26=%26')['status'] == 404 + assert client.get(url='/?&=')['status'] == 404 + + +def test_routes_match_arguments_complex(): + route_match({"arguments": {"foo": ""}}) + + assert client.get(url='/?foo')['status'] == 200, 'complex' + assert client.get(url='/?blah=blah&foo=')['status'] == 200, 'complex 2' + assert client.get(url='/?&&&foo&&&')['status'] == 200, 'complex 3' + assert client.get(url='/?foo&foo=bar&foo')['status'] == 404, 'complex 4' + assert client.get(url='/?foo=&foo')['status'] == 200, 'complex 5' + assert client.get(url='/?&=&foo&==&')['status'] == 200, 'complex 6' + assert client.get(url='/?&=&bar&==&')['status'] == 404, 'complex 7' + + +def test_routes_match_arguments_multiple(): + route_match({"arguments": {"foo": "bar", "blah": "test"}}) + + assert client.get()['status'] == 404, 'multiple' + assert client.get(url='/?foo=bar&blah=test')['status'] == 200, 'multiple 2' + assert client.get(url='/?foo=bar&blah')['status'] == 404, 'multiple 3' + assert client.get(url='/?foo=bar&blah=tes')['status'] == 404, 'multiple 4' + assert ( + client.get(url='/?foo=b%61r&bl%61h=t%65st')['status'] == 200 + ), 'multiple 5' + + +def test_routes_match_arguments_multiple_rules(): + route_match({"arguments": {"foo": ["bar", "blah"]}}) + + assert client.get()['status'] == 404, 'rules' + assert client.get(url='/?foo=bar')['status'] == 200, 'rules 2' + assert client.get(url='/?foo=blah')['status'] == 200, 'rules 3' + assert ( + client.get(url='/?foo=blah&foo=bar&foo=blah')['status'] == 200 + ), 'rules 4' + assert client.get(url='/?foo=blah&foo=bar&foo=')['status'] == 404, 'rules 5' + + +def test_routes_match_arguments_array(): + route_match( + { + "arguments": [ + {"var1": "val1*"}, + {"var2": "val2"}, + {"var3": ["foo", "bar"]}, + {"var1": "bar", "var4": "foo"}, + ] + } + ) + + assert client.get()['status'] == 404, 'arr' + assert client.get(url='/?var1=val123')['status'] == 200, 'arr 2' + assert client.get(url='/?var2=val2')['status'] == 200, 'arr 3' + assert client.get(url='/?var3=bar')['status'] == 200, 'arr 4' + assert client.get(url='/?var1=bar')['status'] == 404, 'arr 5' + assert client.get(url='/?var1=bar&var4=foo')['status'] == 200, 'arr 6' + + assert 'success' in client.conf_delete( + 'routes/0/match/arguments/1' + ), 'match arguments array configure 2' - def test_routes_source_ipv6(self): - assert 'success' in self.conf( - { - "[::1]:7080": {"pass": "routes"}, - "127.0.0.1:7081": {"pass": "routes"}, - }, - 'listeners', - ), 'source listeners configure' + assert client.get(url='/?var2=val2')['status'] == 404, 'arr 7' + assert client.get(url='/?var3=foo')['status'] == 200, 'arr 8' - self.route_match({"source": "::1"}) - assert self.get(sock_type='ipv6')['status'] == 200, 'exact' - assert self.get(port=7081)['status'] == 404, 'exact ipv4' - self.route_match({"source": ["::1"]}) - assert self.get(sock_type='ipv6')['status'] == 200, 'exact 2' - assert self.get(port=7081)['status'] == 404, 'exact 2 ipv4' +def test_routes_match_arguments_invalid(): + route_match_invalid({"arguments": ["var"]}) + route_match_invalid({"arguments": [{"var1": {}}]}) + route_match_invalid({"arguments": {"": "bar"}}) + route_match_invalid({"arguments": {"foo": "%"}}) + route_match_invalid({"arguments": {"foo": "%1G"}}) + route_match_invalid({"arguments": {"%": "bar"}}) + route_match_invalid({"arguments": {"foo": "%0"}}) + route_match_invalid({"arguments": {"foo": "%%1F"}}) + route_match_invalid({"arguments": {"%%1F": ""}}) + route_match_invalid({"arguments": {"%7%F": ""}}) + - self.route_match({"source": "!::1"}) - assert self.get(sock_type='ipv6')['status'] == 404, 'exact neg' - assert self.get(port=7081)['status'] == 200, 'exact neg ipv4' +def test_routes_match_query(): + route_match({"query": "!"}) + assert client.get(url='/')['status'] == 404 + assert client.get(url='/?')['status'] == 404 + assert client.get(url='/?foo')['status'] == 200 + assert client.get(url='/?foo=')['status'] == 200 + assert client.get(url='/?foo=baz')['status'] == 200 - self.route_match({"source": "::2"}) - assert self.get(sock_type='ipv6')['status'] == 404, 'exact 3' - assert self.get(port=7081)['status'] == 404, 'exact 3 ipv4' + route_match({"query": "foo=%26"}) + assert client.get(url='/?foo=&')['status'] == 200 - self.route_match({"source": "::1-::1"}) - assert self.get(sock_type='ipv6')['status'] == 200, 'range' - assert self.get(port=7081)['status'] == 404, 'range ipv4' + route_match({"query": "a=b&c=d"}) + assert client.get(url='/?a=b&c=d')['status'] == 200 - self.route_match({"source": "::2-::2"}) - assert self.get(sock_type='ipv6')['status'] == 404, 'range 2' - assert self.get(port=7081)['status'] == 404, 'range 2 ipv4' + route_match({"query": "a=b%26c%3Dd"}) + assert client.get(url='/?a=b%26c%3Dd')['status'] == 200 + assert client.get(url='/?a=b&c=d')['status'] == 200 - self.route_match({"source": "::2-::3"}) - assert self.get(sock_type='ipv6')['status'] == 404, 'range 3' - assert self.get(port=7081)['status'] == 404, 'range 3 ipv4' + route_match({"query": "a=b%26c%3Dd+e"}) + assert client.get(url='/?a=b&c=d e')['status'] == 200 - self.route_match({"source": "::1-::2"}) - assert self.get(sock_type='ipv6')['status'] == 200, 'range 4' - assert self.get(port=7081)['status'] == 404, 'range 4 ipv4' - self.route_match({"source": "::0-::2"}) - assert self.get(sock_type='ipv6')['status'] == 200, 'range 5' - assert self.get(port=7081)['status'] == 404, 'range 5 ipv4' +def test_routes_match_query_array(): + route_match({"query": ["foo", "bar"]}) - self.route_match({"source": "::0-::1"}) - assert self.get(sock_type='ipv6')['status'] == 200, 'range 6' - assert self.get(port=7081)['status'] == 404, 'range 6 ipv4' + assert client.get()['status'] == 404, 'no args' + assert client.get(url='/?foo')['status'] == 200, 'arg first' + assert client.get(url='/?bar')['status'] == 200, 'arg second' - def test_routes_source_cidr(self): - assert 'success' in self.conf( - { - "*:7080": {"pass": "routes"}, - "[::1]:7081": {"pass": "routes"}, - }, - 'listeners', - ), 'source listeners configure' + assert 'success' in client.conf_delete( + 'routes/0/match/query/1' + ), 'query array remove second' - def get_ipv6(): - return self.get(sock_type='ipv6', port=7081) + assert client.get(url='/?foo')['status'] == 200, 'still arg first' + assert client.get(url='/?bar')['status'] == 404, 'no arg second' - self.route_match({"source": "127.0.0.1/32"}) - assert self.get()['status'] == 200, '32' - assert get_ipv6()['status'] == 404, '32 ipv6' + route_match({"query": ["!f", "foo"]}) - self.route_match({"source": "127.0.0.0/32"}) - assert self.get()['status'] == 404, '32 2' - assert get_ipv6()['status'] == 404, '32 2 ipv6' + assert client.get(url='/?f')['status'] == 404, 'negative arg' + assert client.get(url='/?fo')['status'] == 404, 'negative arg 2' + assert client.get(url='/?foo')['status'] == 200, 'negative arg 3' + + route_match({"query": []}) + assert client.get()['status'] == 200, 'empty array' + + +def test_routes_match_query_invalid(): + route_match_invalid({"query": [1]}) + route_match_invalid({"query": "%"}) + route_match_invalid({"query": "%1G"}) + route_match_invalid({"query": "%0"}) + route_match_invalid({"query": "%%1F"}) + route_match_invalid({"query": ["foo", "%3D", "%%1F"]}) + + +def test_routes_match_cookies(): + route_match({"cookies": {"foO": "bar"}}) - self.route_match({"source": "127.0.0.0/31"}) - assert self.get()['status'] == 200, '31' - assert get_ipv6()['status'] == 404, '31 ipv6' + assert client.get()['status'] == 404, 'cookie' + cookie('foO=bar', 200) + cookie('foO=bar;1', 200) + cookie(['foO=bar', 'blah=blah'], 200) + cookie('foO=bar; blah=blah', 200) + cookie('Foo=bar', 404) + cookie('foO=Bar', 404) + cookie('foO=bar1', 404) + cookie('1foO=bar;', 404) - self.route_match({"source": "0.0.0.0/1"}) - assert self.get()['status'] == 200, '1' - assert get_ipv6()['status'] == 404, '1 ipv6' - self.route_match({"source": "0.0.0.0/0"}) - assert self.get()['status'] == 200, '0' - assert get_ipv6()['status'] == 404, '0 ipv6' +def test_routes_match_cookies_empty(): + route_match({"cookies": {}}) + assert client.get()['status'] == 200, 'cookies empty' - def test_routes_source_cidr_ipv6(self): - assert 'success' in self.conf( - { - "[::1]:7080": {"pass": "routes"}, - "127.0.0.1:7081": {"pass": "routes"}, - }, - 'listeners', - ), 'source listeners configure' + route_match({"cookies": []}) + assert client.get()['status'] == 200, 'cookies empty 2' - self.route_match({"source": "::1/128"}) - assert self.get(sock_type='ipv6')['status'] == 200, '128' - assert self.get(port=7081)['status'] == 404, '128 ipv4' - self.route_match({"source": "::0/128"}) - assert self.get(sock_type='ipv6')['status'] == 404, '128 2' - assert self.get(port=7081)['status'] == 404, '128 ipv4' +def test_routes_match_cookies_invalid(): + route_match_invalid({"cookies": ["var"]}) + route_match_invalid({"cookies": [{"foo": {}}]}) - self.route_match({"source": "::0/127"}) - assert self.get(sock_type='ipv6')['status'] == 200, '127' - assert self.get(port=7081)['status'] == 404, '127 ipv4' - self.route_match({"source": "::0/32"}) - assert self.get(sock_type='ipv6')['status'] == 200, '32' - assert self.get(port=7081)['status'] == 404, '32 ipv4' +def test_routes_match_cookies_complex(): + route_match({"cookies": {"foo": "bar=baz"}}) + cookie('foo=bar=baz', 200) + cookie(' foo=bar=baz ', 200) + cookie('=foo=bar=baz', 404) - self.route_match({"source": "::0/1"}) - assert self.get(sock_type='ipv6')['status'] == 200, '1' - assert self.get(port=7081)['status'] == 404, '1 ipv4' + route_match({"cookies": {"foo": ""}}) + cookie('foo=', 200) + cookie('foo=;', 200) + cookie(' foo=;', 200) + cookie('foo', 404) + cookie('', 404) + cookie('=', 404) - self.route_match({"source": "::/0"}) - assert self.get(sock_type='ipv6')['status'] == 200, '0' - assert self.get(port=7081)['status'] == 404, '0 ipv4' - def test_routes_source_unix(self, temp_dir): - addr = f'{temp_dir}/sock' +def test_routes_match_cookies_multiple(): + route_match({"cookies": {"foo": "bar", "blah": "blah"}}) - assert 'success' in self.conf( - { - "127.0.0.1:7081": {"pass": "routes"}, - f'unix:{addr}': {"pass": "routes"}, - }, - 'listeners', - ), 'source listeners configure' + assert client.get()['status'] == 404, 'multiple' + cookie('foo=bar; blah=blah', 200) + cookie(['foo=bar', 'blah=blah'], 200) + cookie(['foo=bar; blah', 'blah'], 404) + cookie(['foo=bar; blah=test', 'blah=blah'], 404) - self.route_match({"source": "!0.0.0.0/0"}) - assert ( - self.get(sock_type='unix', addr=addr)['status'] == 200 - ), 'unix ipv4 neg' - self.route_match({"source": "!::/0"}) - assert ( - self.get(sock_type='unix', addr=addr)['status'] == 200 - ), 'unix ipv6 neg' +def test_routes_match_cookies_multiple_values(): + route_match({"cookies": {"blah": "blah"}}) - self.route_match({"source": "unix"}) - assert self.get(port=7081)['status'] == 404, 'unix ipv4' - assert self.get(sock_type='unix', addr=addr)['status'] == 200, 'unix' + cookie(['blah=blah', 'blah=blah', 'blah=blah'], 200) + cookie(['blah=blah', 'blah=test', 'blah=blah'], 404) + cookie(['blah=blah; blah=', 'blah=blah'], 404) - def test_routes_match_source(self): - self.route_match({"source": "::"}) - self.route_match( - { - "source": [ - "127.0.0.1", - "192.168.0.10:8080", - "192.168.0.11:8080-8090", - ] - } - ) - self.route_match( - { - "source": [ - "10.0.0.0/8", - "10.0.0.0/7:1000", - "10.0.0.0/32:8080-8090", - ] - } - ) - self.route_match( - { - "source": [ - "10.0.0.0-10.0.0.1", - "10.0.0.0-11.0.0.0:1000", - "127.0.0.0-127.0.0.255:8080-8090", - ] - } - ) - self.route_match( - {"source": ["2001::", "[2002::]:8000", "[2003::]:8080-8090"]} - ) - self.route_match( - { - "source": [ - "2001::-200f:ffff:ffff:ffff:ffff:ffff:ffff:ffff", - "[fe08::-feff::]:8000", - "[fff0::-fff0::10]:8080-8090", - ] - } - ) - self.route_match( - { - "source": [ - "2001::/16", - "[0ff::/64]:8000", - "[fff0:abcd:ffff:ffff:ffff::/128]:8080-8090", - ] - } - ) - self.route_match({"source": "*:0-65535"}) - assert self.get()['status'] == 200, 'source any' - - def test_routes_match_source_invalid(self): - self.route_match_invalid({"source": "127"}) - self.route_match_invalid({"source": "256.0.0.1"}) - self.route_match_invalid({"source": "127.0.0."}) - self.route_match_invalid({"source": " 127.0.0.1"}) - self.route_match_invalid({"source": "127.0.0.1:"}) - self.route_match_invalid({"source": "127.0.0.1/"}) - self.route_match_invalid({"source": "11.0.0.0/33"}) - self.route_match_invalid({"source": "11.0.0.0/65536"}) - self.route_match_invalid({"source": "11.0.0.0-10.0.0.0"}) - self.route_match_invalid({"source": "11.0.0.0:3000-2000"}) - self.route_match_invalid({"source": ["11.0.0.0:3000-2000"]}) - self.route_match_invalid({"source": "[2001::]:3000-2000"}) - self.route_match_invalid({"source": "2001::-2000::"}) - self.route_match_invalid({"source": "2001::/129"}) - self.route_match_invalid({"source": "::FFFFF"}) - self.route_match_invalid({"source": "[::1]:"}) - self.route_match_invalid({"source": "[:::]:7080"}) - self.route_match_invalid({"source": "*:"}) - self.route_match_invalid({"source": "*:1-a"}) - self.route_match_invalid({"source": "*:65536"}) - - def test_routes_match_source_none(self): - self.route_match({"source": []}) - assert self.get()['status'] == 404, 'source none' - - def test_routes_match_destination(self): - assert 'success' in self.conf( - {"*:7080": {"pass": "routes"}, "*:7081": {"pass": "routes"}}, - 'listeners', - ), 'listeners configure' - - self.route_match({"destination": "*:7080"}) - assert self.get()['status'] == 200, 'dest' - assert self.get(port=7081)['status'] == 404, 'dest 2' - - self.route_match({"destination": ["127.0.0.1:7080"]}) - assert self.get()['status'] == 200, 'dest 3' - assert self.get(port=7081)['status'] == 404, 'dest 4' - - self.route_match({"destination": "!*:7080"}) - assert self.get()['status'] == 404, 'dest neg' - assert self.get(port=7081)['status'] == 200, 'dest neg 2' - - self.route_match({"destination": ['!*:7080', '!*:7081']}) - assert self.get()['status'] == 404, 'dest neg 3' - assert self.get(port=7081)['status'] == 404, 'dest neg 4' - - self.route_match({"destination": ['!*:7081', '!*:7082']}) - assert self.get()['status'] == 200, 'dest neg 5' - - self.route_match({"destination": ['*:7080', '!*:7080']}) - assert self.get()['status'] == 404, 'dest neg 6' - - self.route_match( - {"destination": ['127.0.0.1:7080', '*:7081', '!*:7080']} - ) - assert self.get()['status'] == 404, 'dest neg 7' - assert self.get(port=7081)['status'] == 200, 'dest neg 8' - self.route_match({"destination": ['!*:7081', '!*:7082', '*:7083']}) - assert self.get()['status'] == 404, 'dest neg 9' +def test_routes_match_cookies_multiple_rules(): + route_match({"cookies": {"blah": ["test", "blah"]}}) - self.route_match( - {"destination": ['*:7081', '!127.0.0.1:7080', '*:7080']} - ) - assert self.get()['status'] == 404, 'dest neg 10' - assert self.get(port=7081)['status'] == 200, 'dest neg 11' - - assert 'success' in self.conf_delete( - 'routes/0/match/destination/0' - ), 'remove destination rule' - assert self.get()['status'] == 404, 'dest neg 12' - assert self.get(port=7081)['status'] == 404, 'dest neg 13' - - assert 'success' in self.conf_delete( - 'routes/0/match/destination/0' - ), 'remove destination rule 2' - assert self.get()['status'] == 200, 'dest neg 14' - assert self.get(port=7081)['status'] == 404, 'dest neg 15' - - assert 'success' in self.conf_post( - "\"!127.0.0.1\"", 'routes/0/match/destination' - ), 'add destination rule' - assert self.get()['status'] == 404, 'dest neg 16' - assert self.get(port=7081)['status'] == 404, 'dest neg 17' - - def test_routes_match_destination_proxy(self): - assert 'success' in self.conf( - { - "listeners": { - "*:7080": {"pass": "routes/first"}, - "*:7081": {"pass": "routes/second"}, - }, - "routes": { - "first": [{"action": {"proxy": "http://127.0.0.1:7081"}}], - "second": [ - { - "match": {"destination": ["127.0.0.1:7081"]}, - "action": {"return": 200}, - } - ], - }, - "applications": {}, - } - ), 'proxy configure' + assert client.get()['status'] == 404, 'multiple rules' + cookie('blah=test', 200) + cookie('blah=blah', 200) + cookie(['blah=blah', 'blah=test', 'blah=blah'], 200) + cookie(['blah=blah; blah=test', 'blah=blah'], 200) + cookie(['blah=blah', 'blah'], 200) # invalid cookie + + +def test_routes_match_cookies_array(): + route_match( + { + "cookies": [ + {"var1": "val1*"}, + {"var2": "val2"}, + {"var3": ["foo", "bar"]}, + {"var1": "bar", "var4": "foo"}, + ] + } + ) + + assert client.get()['status'] == 404, 'cookies array' + cookie('var1=val123', 200) + cookie('var2=val2', 200) + cookie(' var2=val2 ', 200) + cookie('var3=bar', 200) + cookie('var3=bar;', 200) + cookie('var1=bar', 404) + cookie('var1=bar; var4=foo;', 200) + cookie(['var1=bar', 'var4=foo'], 200) + + assert 'success' in client.conf_delete( + 'routes/0/match/cookies/1' + ), 'match cookies array configure 2' + + cookie('var2=val2', 404) + cookie('var3=foo', 200) + + +def test_routes_match_scheme(): + route_match({"scheme": "http"}) + route_match({"scheme": "https"}) + route_match({"scheme": "HtTp"}) + route_match({"scheme": "HtTpS"}) + + +def test_routes_match_scheme_invalid(): + route_match_invalid({"scheme": ["http"]}) + route_match_invalid({"scheme": "ftp"}) + route_match_invalid({"scheme": "ws"}) + route_match_invalid({"scheme": "*"}) + route_match_invalid({"scheme": ""}) + + +def test_routes_source_port(): + def sock_port(): + sock = client.http(b'', raw=True, no_recv=True) + port = sock.getsockname()[1] + return (sock, port) + + sock, port = sock_port() + sock2, _ = sock_port() + + route_match({"source": f'127.0.0.1:{port}'}) + assert client.get(sock=sock)['status'] == 200, 'exact' + assert client.get(sock=sock2)['status'] == 404, 'exact 2' + + sock, port = sock_port() + sock2, _ = sock_port() + + route_match({"source": f'!127.0.0.1:{port}'}) + assert client.get(sock=sock)['status'] == 404, 'negative' + assert client.get(sock=sock2)['status'] == 200, 'negative 2' + + sock, port = sock_port() + sock2, _ = sock_port() + + route_match({"source": [f'*:{port}', "!127.0.0.1"]}) + assert client.get(sock=sock)['status'] == 404, 'negative 3' + assert client.get(sock=sock2)['status'] == 404, 'negative 4' + + sock, port = sock_port() + sock2, _ = sock_port() + + route_match({"source": f'127.0.0.1:{port}-{port}'}) + assert client.get(sock=sock)['status'] == 200, 'range single' + assert client.get(sock=sock2)['status'] == 404, 'range single 2' + + socks = [ + sock_port(), + sock_port(), + sock_port(), + sock_port(), + sock_port(), + ] + socks.sort(key=lambda sock: sock[1]) + + route_match({"source": f'127.0.0.1:{socks[1][1]}-{socks[3][1]}'}) + assert client.get(sock=socks[0][0])['status'] == 404, 'range' + assert client.get(sock=socks[1][0])['status'] == 200, 'range 2' + assert client.get(sock=socks[2][0])['status'] == 200, 'range 3' + assert client.get(sock=socks[3][0])['status'] == 200, 'range 4' + assert client.get(sock=socks[4][0])['status'] == 404, 'range 5' + + socks = [ + sock_port(), + sock_port(), + sock_port(), + ] + socks.sort(key=lambda sock: sock[1]) + + route_match( + { + "source": [ + f'127.0.0.1:{socks[0][1]}', + f'127.0.0.1:{socks[2][1]}', + ] + } + ) + assert client.get(sock=socks[0][0])['status'] == 200, 'array' + assert client.get(sock=socks[1][0])['status'] == 404, 'array 2' + assert client.get(sock=socks[2][0])['status'] == 200, 'array 3' + + +def test_routes_source_addr(): + assert 'success' in client.conf( + { + "*:7080": {"pass": "routes"}, + "[::1]:7081": {"pass": "routes"}, + }, + 'listeners', + ), 'source listeners configure' + + def get_ipv6(): + return client.get(sock_type='ipv6', port=7081) + + route_match({"source": "127.0.0.1"}) + assert client.get()['status'] == 200, 'exact' + assert get_ipv6()['status'] == 404, 'exact ipv6' + + route_match({"source": ["127.0.0.1"]}) + assert client.get()['status'] == 200, 'exact 2' + assert get_ipv6()['status'] == 404, 'exact 2 ipv6' + + route_match({"source": "!127.0.0.1"}) + assert client.get()['status'] == 404, 'exact neg' + assert get_ipv6()['status'] == 200, 'exact neg ipv6' + + route_match({"source": "127.0.0.2"}) + assert client.get()['status'] == 404, 'exact 3' + assert get_ipv6()['status'] == 404, 'exact 3 ipv6' + + route_match({"source": "127.0.0.1-127.0.0.1"}) + assert client.get()['status'] == 200, 'range single' + assert get_ipv6()['status'] == 404, 'range single ipv6' + + route_match({"source": "127.0.0.2-127.0.0.2"}) + assert client.get()['status'] == 404, 'range single 2' + assert get_ipv6()['status'] == 404, 'range single 2 ipv6' + + route_match({"source": "127.0.0.2-127.0.0.3"}) + assert client.get()['status'] == 404, 'range' + assert get_ipv6()['status'] == 404, 'range ipv6' + + route_match({"source": "127.0.0.1-127.0.0.2"}) + assert client.get()['status'] == 200, 'range 2' + assert get_ipv6()['status'] == 404, 'range 2 ipv6' + + route_match({"source": "127.0.0.0-127.0.0.2"}) + assert client.get()['status'] == 200, 'range 3' + assert get_ipv6()['status'] == 404, 'range 3 ipv6' + + route_match({"source": "127.0.0.0-127.0.0.1"}) + assert client.get()['status'] == 200, 'range 4' + assert get_ipv6()['status'] == 404, 'range 4 ipv6' + + route_match({"source": "126.0.0.0-127.0.0.0"}) + assert client.get()['status'] == 404, 'range 5' + assert get_ipv6()['status'] == 404, 'range 5 ipv6' + + route_match({"source": "126.126.126.126-127.0.0.2"}) + assert client.get()['status'] == 200, 'range 6' + assert get_ipv6()['status'] == 404, 'range 6 ipv6' + + +def test_routes_source_ipv6(): + assert 'success' in client.conf( + { + "[::1]:7080": {"pass": "routes"}, + "127.0.0.1:7081": {"pass": "routes"}, + }, + 'listeners', + ), 'source listeners configure' + + route_match({"source": "::1"}) + assert client.get(sock_type='ipv6')['status'] == 200, 'exact' + assert client.get(port=7081)['status'] == 404, 'exact ipv4' + + route_match({"source": ["::1"]}) + assert client.get(sock_type='ipv6')['status'] == 200, 'exact 2' + assert client.get(port=7081)['status'] == 404, 'exact 2 ipv4' + + route_match({"source": "!::1"}) + assert client.get(sock_type='ipv6')['status'] == 404, 'exact neg' + assert client.get(port=7081)['status'] == 200, 'exact neg ipv4' + + route_match({"source": "::2"}) + assert client.get(sock_type='ipv6')['status'] == 404, 'exact 3' + assert client.get(port=7081)['status'] == 404, 'exact 3 ipv4' + + route_match({"source": "::1-::1"}) + assert client.get(sock_type='ipv6')['status'] == 200, 'range' + assert client.get(port=7081)['status'] == 404, 'range ipv4' + + route_match({"source": "::2-::2"}) + assert client.get(sock_type='ipv6')['status'] == 404, 'range 2' + assert client.get(port=7081)['status'] == 404, 'range 2 ipv4' + + route_match({"source": "::2-::3"}) + assert client.get(sock_type='ipv6')['status'] == 404, 'range 3' + assert client.get(port=7081)['status'] == 404, 'range 3 ipv4' + + route_match({"source": "::1-::2"}) + assert client.get(sock_type='ipv6')['status'] == 200, 'range 4' + assert client.get(port=7081)['status'] == 404, 'range 4 ipv4' + + route_match({"source": "::0-::2"}) + assert client.get(sock_type='ipv6')['status'] == 200, 'range 5' + assert client.get(port=7081)['status'] == 404, 'range 5 ipv4' + + route_match({"source": "::0-::1"}) + assert client.get(sock_type='ipv6')['status'] == 200, 'range 6' + assert client.get(port=7081)['status'] == 404, 'range 6 ipv4' + + +def test_routes_source_cidr(): + assert 'success' in client.conf( + { + "*:7080": {"pass": "routes"}, + "[::1]:7081": {"pass": "routes"}, + }, + 'listeners', + ), 'source listeners configure' + + def get_ipv6(): + return client.get(sock_type='ipv6', port=7081) + + route_match({"source": "127.0.0.1/32"}) + assert client.get()['status'] == 200, '32' + assert get_ipv6()['status'] == 404, '32 ipv6' + + route_match({"source": "127.0.0.0/32"}) + assert client.get()['status'] == 404, '32 2' + assert get_ipv6()['status'] == 404, '32 2 ipv6' + + route_match({"source": "127.0.0.0/31"}) + assert client.get()['status'] == 200, '31' + assert get_ipv6()['status'] == 404, '31 ipv6' + + route_match({"source": "0.0.0.0/1"}) + assert client.get()['status'] == 200, '1' + assert get_ipv6()['status'] == 404, '1 ipv6' + + route_match({"source": "0.0.0.0/0"}) + assert client.get()['status'] == 200, '0' + assert get_ipv6()['status'] == 404, '0 ipv6' + + +def test_routes_source_cidr_ipv6(): + assert 'success' in client.conf( + { + "[::1]:7080": {"pass": "routes"}, + "127.0.0.1:7081": {"pass": "routes"}, + }, + 'listeners', + ), 'source listeners configure' + + route_match({"source": "::1/128"}) + assert client.get(sock_type='ipv6')['status'] == 200, '128' + assert client.get(port=7081)['status'] == 404, '128 ipv4' + + route_match({"source": "::0/128"}) + assert client.get(sock_type='ipv6')['status'] == 404, '128 2' + assert client.get(port=7081)['status'] == 404, '128 ipv4' + + route_match({"source": "::0/127"}) + assert client.get(sock_type='ipv6')['status'] == 200, '127' + assert client.get(port=7081)['status'] == 404, '127 ipv4' + + route_match({"source": "::0/32"}) + assert client.get(sock_type='ipv6')['status'] == 200, '32' + assert client.get(port=7081)['status'] == 404, '32 ipv4' + + route_match({"source": "::0/1"}) + assert client.get(sock_type='ipv6')['status'] == 200, '1' + assert client.get(port=7081)['status'] == 404, '1 ipv4' + + route_match({"source": "::/0"}) + assert client.get(sock_type='ipv6')['status'] == 200, '0' + assert client.get(port=7081)['status'] == 404, '0 ipv4' + + +def test_routes_source_unix(temp_dir): + addr = f'{temp_dir}/sock' + + assert 'success' in client.conf( + { + "127.0.0.1:7081": {"pass": "routes"}, + f'unix:{addr}': {"pass": "routes"}, + }, + 'listeners', + ), 'source listeners configure' + + route_match({"source": "!0.0.0.0/0"}) + assert ( + client.get(sock_type='unix', addr=addr)['status'] == 200 + ), 'unix ipv4 neg' + + route_match({"source": "!::/0"}) + assert ( + client.get(sock_type='unix', addr=addr)['status'] == 200 + ), 'unix ipv6 neg' + + route_match({"source": "unix"}) + assert client.get(port=7081)['status'] == 404, 'unix ipv4' + assert client.get(sock_type='unix', addr=addr)['status'] == 200, 'unix' + + +def test_routes_match_source(): + route_match({"source": "::"}) + route_match( + { + "source": [ + "127.0.0.1", + "192.168.0.10:8080", + "192.168.0.11:8080-8090", + ] + } + ) + route_match( + { + "source": [ + "10.0.0.0/8", + "10.0.0.0/7:1000", + "10.0.0.0/32:8080-8090", + ] + } + ) + route_match( + { + "source": [ + "10.0.0.0-10.0.0.1", + "10.0.0.0-11.0.0.0:1000", + "127.0.0.0-127.0.0.255:8080-8090", + ] + } + ) + route_match({"source": ["2001::", "[2002::]:8000", "[2003::]:8080-8090"]}) + route_match( + { + "source": [ + "2001::-200f:ffff:ffff:ffff:ffff:ffff:ffff:ffff", + "[fe08::-feff::]:8000", + "[fff0::-fff0::10]:8080-8090", + ] + } + ) + route_match( + { + "source": [ + "2001::/16", + "[0ff::/64]:8000", + "[fff0:abcd:ffff:ffff:ffff::/128]:8080-8090", + ] + } + ) + route_match({"source": "*:0-65535"}) + assert client.get()['status'] == 200, 'source any' + + +def test_routes_match_source_invalid(): + route_match_invalid({"source": "127"}) + route_match_invalid({"source": "256.0.0.1"}) + route_match_invalid({"source": "127.0.0."}) + route_match_invalid({"source": " 127.0.0.1"}) + route_match_invalid({"source": "127.0.0.1:"}) + route_match_invalid({"source": "127.0.0.1/"}) + route_match_invalid({"source": "11.0.0.0/33"}) + route_match_invalid({"source": "11.0.0.0/65536"}) + route_match_invalid({"source": "11.0.0.0-10.0.0.0"}) + route_match_invalid({"source": "11.0.0.0:3000-2000"}) + route_match_invalid({"source": ["11.0.0.0:3000-2000"]}) + route_match_invalid({"source": "[2001::]:3000-2000"}) + route_match_invalid({"source": "2001::-2000::"}) + route_match_invalid({"source": "2001::/129"}) + route_match_invalid({"source": "::FFFFF"}) + route_match_invalid({"source": "[::1]:"}) + route_match_invalid({"source": "[:::]:7080"}) + route_match_invalid({"source": "*:"}) + route_match_invalid({"source": "*:1-a"}) + route_match_invalid({"source": "*:65536"}) + + +def test_routes_match_source_none(): + route_match({"source": []}) + assert client.get()['status'] == 404, 'source none' + + +def test_routes_match_destination(): + assert 'success' in client.conf( + {"*:7080": {"pass": "routes"}, "*:7081": {"pass": "routes"}}, + 'listeners', + ), 'listeners configure' + + route_match({"destination": "*:7080"}) + assert client.get()['status'] == 200, 'dest' + assert client.get(port=7081)['status'] == 404, 'dest 2' + + route_match({"destination": ["127.0.0.1:7080"]}) + assert client.get()['status'] == 200, 'dest 3' + assert client.get(port=7081)['status'] == 404, 'dest 4' + + route_match({"destination": "!*:7080"}) + assert client.get()['status'] == 404, 'dest neg' + assert client.get(port=7081)['status'] == 200, 'dest neg 2' + + route_match({"destination": ['!*:7080', '!*:7081']}) + assert client.get()['status'] == 404, 'dest neg 3' + assert client.get(port=7081)['status'] == 404, 'dest neg 4' + + route_match({"destination": ['!*:7081', '!*:7082']}) + assert client.get()['status'] == 200, 'dest neg 5' + + route_match({"destination": ['*:7080', '!*:7080']}) + assert client.get()['status'] == 404, 'dest neg 6' + + route_match({"destination": ['127.0.0.1:7080', '*:7081', '!*:7080']}) + assert client.get()['status'] == 404, 'dest neg 7' + assert client.get(port=7081)['status'] == 200, 'dest neg 8' + + route_match({"destination": ['!*:7081', '!*:7082', '*:7083']}) + assert client.get()['status'] == 404, 'dest neg 9' + + route_match({"destination": ['*:7081', '!127.0.0.1:7080', '*:7080']}) + assert client.get()['status'] == 404, 'dest neg 10' + assert client.get(port=7081)['status'] == 200, 'dest neg 11' + + assert 'success' in client.conf_delete( + 'routes/0/match/destination/0' + ), 'remove destination rule' + assert client.get()['status'] == 404, 'dest neg 12' + assert client.get(port=7081)['status'] == 404, 'dest neg 13' + + assert 'success' in client.conf_delete( + 'routes/0/match/destination/0' + ), 'remove destination rule 2' + assert client.get()['status'] == 200, 'dest neg 14' + assert client.get(port=7081)['status'] == 404, 'dest neg 15' + + assert 'success' in client.conf_post( + "\"!127.0.0.1\"", 'routes/0/match/destination' + ), 'add destination rule' + assert client.get()['status'] == 404, 'dest neg 16' + assert client.get(port=7081)['status'] == 404, 'dest neg 17' + + +def test_routes_match_destination_proxy(): + assert 'success' in client.conf( + { + "listeners": { + "*:7080": {"pass": "routes/first"}, + "*:7081": {"pass": "routes/second"}, + }, + "routes": { + "first": [{"action": {"proxy": "http://127.0.0.1:7081"}}], + "second": [ + { + "match": {"destination": ["127.0.0.1:7081"]}, + "action": {"return": 200}, + } + ], + }, + "applications": {}, + } + ), 'proxy configure' - assert self.get()['status'] == 200, 'proxy' + assert client.get()['status'] == 200, 'proxy' |