From 79b2a8ca3039f70ce2a2073aece3305c90ddab08 Mon Sep 17 00:00:00 2001 From: Abhinav Singh Date: Sun, 5 Jun 2022 22:14:17 +0530 Subject: [PATCH 1/8] Add support for dynamic reverse proxy routing. Plugins must implement the `handle_route(self, request, pattern) -> Url` method from the base class to provide a choice of upstream url to serve. This work is backward compatible a.k.a. Old style static route patterns with hardcoded upstream urls will continue to work as-is. See `ReverseProxyBasePlugin` documentation for more details. --- .github/FUNDING.yml | 1 + proxy/http/server/plugin.py | 38 ++++++++++++++++++++++-- proxy/http/server/reverse.py | 54 +++++++++++++++++------------------ proxy/plugin/reverse_proxy.py | 54 ++++++++++++++++++++++++----------- 4 files changed, 99 insertions(+), 48 deletions(-) diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml index 60439f2798..2fa2380906 100644 --- a/.github/FUNDING.yml +++ b/.github/FUNDING.yml @@ -1,3 +1,4 @@ +--- # These are supported funding model platforms github: abhinavsingh diff --git a/proxy/http/server/plugin.py b/proxy/http/server/plugin.py index 0115558c18..76e4245c12 100644 --- a/proxy/http/server/plugin.py +++ b/proxy/http/server/plugin.py @@ -8,11 +8,13 @@ :copyright: (c) 2013-present by Abhinav Singh and contributors. :license: BSD, see LICENSE for more details. """ +import re import argparse import mimetypes from abc import ABC, abstractmethod -from typing import TYPE_CHECKING, Any, Dict, List, Tuple, Optional +from typing import TYPE_CHECKING, Any, Dict, List, Tuple, Union, Optional +from proxy.http.url import Url from ..parser import HttpParser from ..responses import NOT_FOUND_RESPONSE_PKT, okResponse from ..websocket import WebsocketFrame @@ -127,6 +129,36 @@ class ReverseProxyBasePlugin(ABC): """ReverseProxy base plugin class.""" @abstractmethod - def routes(self) -> List[Tuple[str, List[bytes]]]: - """Return List(path, List(upstream)) reverse proxy config.""" + def routes(self) -> List[Union[str, Tuple[str, List[bytes]]]]: + """List of routes registered by plugin. + + There are 2 types of routes: + + 1) Dynamic routes (str): Should be a regular expression + 2) Static routes (tuple): Contain 2 elements, a route regular expression + and list of upstream urls to serve when the route matches. + + Static routes doesn't require you to implement the `handle_route` method. + Reverse proxy core will automatically pick one of the configured upstream URL + and serve it out-of-box. + + Dynamic routes are helpful when you want to dynamically match and serve upstream urls. + To handle dynamic routes, you must implement the `handle_route` method, which + must return the url to serve.""" raise NotImplementedError() # pragma: no cover + + def handle_route(self, request: HttpParser, pattern: re.Pattern) -> Url: + """Implement this method if you have configured dynamic routes.""" + pass + + def regexes(self) -> List[str]: + """Helper method to return list of route regular expressions.""" + routes = [] + for route in self.routes(): + if isinstance(route, str): + routes.append(route) + elif isinstance(route, tuple): + routes.append(route[0]) + else: + raise ValueError("Invalid route type") + return routes diff --git a/proxy/http/server/reverse.py b/proxy/http/server/reverse.py index 45afe1f91f..ca3c3ea646 100644 --- a/proxy/http/server/reverse.py +++ b/proxy/http/server/reverse.py @@ -38,37 +38,40 @@ class ReverseProxy(TcpUpstreamConnectionHandler, HttpWebServerBasePlugin): def __init__(self, *args: Any, **kwargs: Any): super().__init__(*args, **kwargs) self.choice: Optional[Url] = None - self.reverse: Dict[str, List[bytes]] = {} + self.plugins: List['ReverseProxyBasePlugin'] = [] + for klass in self.flags.plugins[b'ReverseProxyBasePlugin']: + plugin: 'ReverseProxyBasePlugin' = klass() + self.plugins.append(plugin) def handle_upstream_data(self, raw: memoryview) -> None: self.client.queue(raw) def routes(self) -> List[Tuple[int, str]]: - reverse: List[Tuple[str, List[bytes]]] = [] - for klass in self.flags.plugins[b'ReverseProxyBasePlugin']: - instance: 'ReverseProxyBasePlugin' = klass() - reverse.extend(instance.routes()) r = [] - for (route, upstreams) in reverse: - r.append((httpProtocolTypes.HTTP, route)) - r.append((httpProtocolTypes.HTTPS, route)) - self.reverse[route] = upstreams + for plugin in self.plugins: + for route in plugin.regexes(): + r.append((httpProtocolTypes.HTTP, route)) + r.append((httpProtocolTypes.HTTPS, route)) return r def handle_request(self, request: HttpParser) -> None: - # TODO: Core must be capable of dispatching a context - # with each invocation of handle request callback. - # - # Example, here we don't know which of our registered - # route actually matched. - # - for route in self.reverse: - pattern = re.compile(route) - if pattern.match(text_(request.path)): - self.choice = Url.from_bytes( - random.choice(self.reverse[route]), - ) - break + for plugin in self.plugins: + for route in plugin.routes(): + if isinstance(route, tuple): + pattern = re.compile(route[0]) + if pattern.match(text_(request.path)): + self.choice = Url.from_bytes( + random.choice(route[1]), + ) + break + elif isinstance(route, str): + pattern = re.compile(route) + if pattern.match(text_(request.path)): + self.choice = plugin.handle_route(request, pattern) + break + else: + raise ValueError("Invalid route") + print(self.choice) assert self.choice and self.choice.hostname port = self.choice.port or \ DEFAULT_HTTP_PORT \ @@ -85,12 +88,7 @@ def handle_request(self, request: HttpParser) -> None: ), as_non_blocking=True, ) - # Update Host header - # if request.has_header(b'Host'): - # request.del_header(b'Host') - # request.add_header( - # b'Host', ('%s:%d' % self.upstream.addr).encode('utf-8'), - # ) + request.path = self.choice.remainder self.upstream.queue(memoryview(request.build())) except ConnectionRefusedError: raise HttpProtocolException( # pragma: no cover diff --git a/proxy/plugin/reverse_proxy.py b/proxy/plugin/reverse_proxy.py index 01eca2b09d..bc59642d29 100644 --- a/proxy/plugin/reverse_proxy.py +++ b/proxy/plugin/reverse_proxy.py @@ -8,22 +8,13 @@ :copyright: (c) 2013-present by Abhinav Singh and contributors. :license: BSD, see LICENSE for more details. """ -from typing import List, Tuple +import re +from typing import List, Tuple, Union +from ..http import Url +from ..http.parser import HttpParser from ..http.server import ReverseProxyBasePlugin - - -# TODO: We must use nginx python parser and -# make this plugin nginx.conf complaint. -REVERSE_PROXY_LOCATION: str = r'/get$' -# Randomly choose either http or https upstream endpoint. -# -# This is just to demonstrate that both http and https upstream -# reverse proxy works. -REVERSE_PROXY_PASS = [ - b'http://httpbin.org/get', - b'https://httpbin.org/get', -] +from ..http.exception.base import HttpProtocolException class ReverseProxyPlugin(ReverseProxyBasePlugin): @@ -35,8 +26,37 @@ class ReverseProxyPlugin(ReverseProxyBasePlugin): } ``` - Update the routes config before. + Plugin also demonstrates how to write "Python" equivalent for any + "Nginx Lua" based configuration i.e. your plugin code will have + full control over what do after one of your route has matched. """ - def routes(self) -> List[Tuple[str, List[bytes]]]: - return [(REVERSE_PROXY_LOCATION, REVERSE_PROXY_PASS)] + def routes(self) -> List[Union[str, Tuple[str, List[bytes]]]]: + return [ + # A static route + ( + r'/get$', + [b'http://httpbin.org/get', b'https://httpbin.org/get'] + ), + # A dynamic route to catch requests on `/get/` + # See `handle_route` method for what we do when a pattern matches. + r'/get/(\d+)$', + ] + + def handle_route(self, request: HttpParser, pattern: re.Pattern) -> Url: + """For our example dynamic route, we want to simply convert + any incoming request to `/get/1` into `/get?id=1` when serving from upstream. + """ + choice: Url = Url.from_bytes(b'http://httpbin.org/get') + assert request.path + result = re.search(pattern, request.path.decode()) + if not result or len(result.groups()) != 1: + raise HttpProtocolException("Invalid request") + assert choice.remainder == b'/get' + # NOTE: Internally, reverse proxy core replaces + # original request.path with the choice.remainder value. + # e.g. for this example, request.path will be `/get/1`. + # Core will automatically replace that with `/get?id=1` + # before dispatching request to choice of upstream server. + choice.remainder += f'?id={result.groups()[0]}'.encode() + return choice From 1096515e8eb10247b41394c66b092cb74e2dc633 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sun, 5 Jun 2022 16:48:32 +0000 Subject: [PATCH 2/8] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- proxy/http/server/plugin.py | 2 +- proxy/http/server/reverse.py | 2 +- proxy/plugin/reverse_proxy.py | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/proxy/http/server/plugin.py b/proxy/http/server/plugin.py index 76e4245c12..a155c7e639 100644 --- a/proxy/http/server/plugin.py +++ b/proxy/http/server/plugin.py @@ -160,5 +160,5 @@ def regexes(self) -> List[str]: elif isinstance(route, tuple): routes.append(route[0]) else: - raise ValueError("Invalid route type") + raise ValueError('Invalid route type') return routes diff --git a/proxy/http/server/reverse.py b/proxy/http/server/reverse.py index ca3c3ea646..e5aa8185a3 100644 --- a/proxy/http/server/reverse.py +++ b/proxy/http/server/reverse.py @@ -70,7 +70,7 @@ def handle_request(self, request: HttpParser) -> None: self.choice = plugin.handle_route(request, pattern) break else: - raise ValueError("Invalid route") + raise ValueError('Invalid route') print(self.choice) assert self.choice and self.choice.hostname port = self.choice.port or \ diff --git a/proxy/plugin/reverse_proxy.py b/proxy/plugin/reverse_proxy.py index bc59642d29..d3173ede71 100644 --- a/proxy/plugin/reverse_proxy.py +++ b/proxy/plugin/reverse_proxy.py @@ -36,7 +36,7 @@ def routes(self) -> List[Union[str, Tuple[str, List[bytes]]]]: # A static route ( r'/get$', - [b'http://httpbin.org/get', b'https://httpbin.org/get'] + [b'http://httpbin.org/get', b'https://httpbin.org/get'], ), # A dynamic route to catch requests on `/get/` # See `handle_route` method for what we do when a pattern matches. @@ -51,7 +51,7 @@ def handle_route(self, request: HttpParser, pattern: re.Pattern) -> Url: assert request.path result = re.search(pattern, request.path.decode()) if not result or len(result.groups()) != 1: - raise HttpProtocolException("Invalid request") + raise HttpProtocolException('Invalid request') assert choice.remainder == b'/get' # NOTE: Internally, reverse proxy core replaces # original request.path with the choice.remainder value. From fd11d34b05a23a73e4f1c068781c6b2833102f2c Mon Sep 17 00:00:00 2001 From: Abhinav Singh Date: Sun, 5 Jun 2022 22:41:29 +0530 Subject: [PATCH 3/8] Address type issues --- proxy/http/server/plugin.py | 4 ++-- proxy/http/server/reverse.py | 2 +- proxy/plugin/reverse_proxy.py | 23 ++++++++++++++--------- 3 files changed, 17 insertions(+), 12 deletions(-) diff --git a/proxy/http/server/plugin.py b/proxy/http/server/plugin.py index 76e4245c12..74765a4f95 100644 --- a/proxy/http/server/plugin.py +++ b/proxy/http/server/plugin.py @@ -147,7 +147,7 @@ def routes(self) -> List[Union[str, Tuple[str, List[bytes]]]]: must return the url to serve.""" raise NotImplementedError() # pragma: no cover - def handle_route(self, request: HttpParser, pattern: re.Pattern) -> Url: + def handle_route(self, request: HttpParser, pattern: re.Pattern[Any]) -> Url: """Implement this method if you have configured dynamic routes.""" pass @@ -160,5 +160,5 @@ def regexes(self) -> List[str]: elif isinstance(route, tuple): routes.append(route[0]) else: - raise ValueError("Invalid route type") + raise ValueError('Invalid route type') return routes diff --git a/proxy/http/server/reverse.py b/proxy/http/server/reverse.py index ca3c3ea646..e5aa8185a3 100644 --- a/proxy/http/server/reverse.py +++ b/proxy/http/server/reverse.py @@ -70,7 +70,7 @@ def handle_request(self, request: HttpParser) -> None: self.choice = plugin.handle_route(request, pattern) break else: - raise ValueError("Invalid route") + raise ValueError('Invalid route') print(self.choice) assert self.choice and self.choice.hostname port = self.choice.port or \ diff --git a/proxy/plugin/reverse_proxy.py b/proxy/plugin/reverse_proxy.py index bc59642d29..4c5b46700f 100644 --- a/proxy/plugin/reverse_proxy.py +++ b/proxy/plugin/reverse_proxy.py @@ -7,9 +7,13 @@ :copyright: (c) 2013-present by Abhinav Singh and contributors. :license: BSD, see LICENSE for more details. + + .. spelling:: + + Lua """ import re -from typing import List, Tuple, Union +from typing import Any, List, Tuple, Union from ..http import Url from ..http.parser import HttpParser @@ -36,27 +40,28 @@ def routes(self) -> List[Union[str, Tuple[str, List[bytes]]]]: # A static route ( r'/get$', - [b'http://httpbin.org/get', b'https://httpbin.org/get'] + [b'http://httpbin.org/get', b'https://httpbin.org/get'], ), - # A dynamic route to catch requests on `/get/` - # See `handle_route` method for what we do when a pattern matches. + # A dynamic route to catch requests on "/get/"" + # See "handle_route" method below for what we do when + # this pattern matches. r'/get/(\d+)$', ] - def handle_route(self, request: HttpParser, pattern: re.Pattern) -> Url: + def handle_route(self, request: HttpParser, pattern: re.Pattern[Any]) -> Url: """For our example dynamic route, we want to simply convert - any incoming request to `/get/1` into `/get?id=1` when serving from upstream. + any incoming request to "/get/1" into "/get?id=1" when serving from upstream. """ choice: Url = Url.from_bytes(b'http://httpbin.org/get') assert request.path result = re.search(pattern, request.path.decode()) if not result or len(result.groups()) != 1: - raise HttpProtocolException("Invalid request") + raise HttpProtocolException('Invalid request') assert choice.remainder == b'/get' # NOTE: Internally, reverse proxy core replaces # original request.path with the choice.remainder value. - # e.g. for this example, request.path will be `/get/1`. - # Core will automatically replace that with `/get?id=1` + # e.g. for this example, request.path will be "/get/1". + # Core will automatically replace that with "/get?id=1" # before dispatching request to choice of upstream server. choice.remainder += f'?id={result.groups()[0]}'.encode() return choice From 69d12e8b83c1aae752df18788cef47d53a8d07a5 Mon Sep 17 00:00:00 2001 From: Abhinav Singh Date: Sun, 5 Jun 2022 23:31:00 +0530 Subject: [PATCH 4/8] Fix spellcheck --- docs/conf.py | 1 + proxy/plugin/__init__.py | 1 + 2 files changed, 2 insertions(+) diff --git a/docs/conf.py b/docs/conf.py index 20d20df6c9..40573d5edc 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -320,6 +320,7 @@ (_py_class_role, 'T'), (_py_class_role, 'HostPort'), (_py_class_role, 'TcpOrTlsSocket'), + (_py_class_role, 're.Pattern'), (_py_obj_role, 'proxy.core.work.threadless.T'), (_py_obj_role, 'proxy.core.work.work.T'), (_py_obj_role, 'proxy.core.base.tcp_server.T'), diff --git a/proxy/plugin/__init__.py b/proxy/plugin/__init__.py index 0d89ba86e7..c3ad91945b 100644 --- a/proxy/plugin/__init__.py +++ b/proxy/plugin/__init__.py @@ -15,6 +15,7 @@ onmessage httpbin localhost + Lua """ from .cache import CacheResponsesPlugin, BaseCacheResponsesPlugin from .shortlink import ShortLinkPlugin From 57202b1444dd4306a26b9bdc200f823ae62aa958 Mon Sep 17 00:00:00 2001 From: Abhinav Singh Date: Sat, 11 Jun 2022 22:27:34 +0530 Subject: [PATCH 5/8] Attempt to solve type errors --- README.md | 16 ++++++++-------- proxy/common/types.py | 9 +++++++++ proxy/http/server/plugin.py | 4 ++-- proxy/plugin/reverse_proxy.py | 5 +++-- 4 files changed, 22 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 273a6bcece..a0a2f9b49b 100644 --- a/README.md +++ b/README.md @@ -2315,9 +2315,9 @@ usage: -m [-h] [--tunnel-hostname TUNNEL_HOSTNAME] [--tunnel-port TUNNEL_PORT] [--filtered-client-ips FILTERED_CLIENT_IPS] [--filtered-url-regex-config FILTERED_URL_REGEX_CONFIG] -proxy.py v2.4.2.dev11+g0beb02d.d20220420 +proxy.py v2.4.3.dev14+gc6b2de6.d20220605 -options: +optional arguments: -h, --help show this help message and exit --tunnel-hostname TUNNEL_HOSTNAME Default: None. Remote hostname or IP address to which @@ -2334,11 +2334,11 @@ options: --tunnel-remote-port TUNNEL_REMOTE_PORT Default: 8899. Remote port which will be forwarded locally for proxy. - --threadless Default: True. Enabled by default on Python 3.8+ (mac, - linux). When disabled a new thread is spawned to + --threadless Default: False. Enabled by default on Python 3.8+ + (mac, linux). When disabled a new thread is spawned to handle each client connection. - --threaded Default: False. Disabled by default on Python < 3.8 - and windows. When enabled a new thread is spawned to + --threaded Default: True. Disabled by default on Python < 3.8 and + windows. When enabled a new thread is spawned to handle each client connection. --num-workers NUM_WORKERS Defaults to number of CPU cores. @@ -2434,8 +2434,8 @@ options: Default: None. Signing certificate to use for signing dynamically generated HTTPS certificates. If used, must also pass --ca-key-file and --ca-signing-key-file - --ca-file CA_FILE Default: /Users/abhinavsingh/Dev/proxy.py/venv310/lib/ - python3.10/site-packages/certifi/cacert.pem. Provide + --ca-file CA_FILE Default: /Users/abhinavsingh/Dev/proxy.py/venv373/lib/ + python3.7/site-packages/certifi/cacert.pem. Provide path to custom CA bundle for peer certificate verification --ca-signing-key-file CA_SIGNING_KEY_FILE diff --git a/proxy/common/types.py b/proxy/common/types.py index 603dd9524d..5d88c6a0d2 100644 --- a/proxy/common/types.py +++ b/proxy/common/types.py @@ -8,10 +8,12 @@ :copyright: (c) 2013-present by Abhinav Singh and contributors. :license: BSD, see LICENSE for more details. """ +import re import ssl import queue import socket import ipaddress +import sys from typing import TYPE_CHECKING, Any, Dict, List, Tuple, Union @@ -30,3 +32,10 @@ IpAddress = Union[ipaddress.IPv4Address, ipaddress.IPv6Address] TcpOrTlsSocket = Union[ssl.SSLSocket, socket.socket] HostPort = Tuple[str, int] + +if sys.version_info.minor == 6: + RePattern = Any +elif sys.version_info.minor == 7: + RePattern = re.Pattern # type: ignore +else: + RePattern = re.Pattern[Any] # type: ignore diff --git a/proxy/http/server/plugin.py b/proxy/http/server/plugin.py index 74765a4f95..0f2cb0171a 100644 --- a/proxy/http/server/plugin.py +++ b/proxy/http/server/plugin.py @@ -8,7 +8,6 @@ :copyright: (c) 2013-present by Abhinav Singh and contributors. :license: BSD, see LICENSE for more details. """ -import re import argparse import mimetypes from abc import ABC, abstractmethod @@ -22,6 +21,7 @@ from ...core.event import EventQueue from ..descriptors import DescriptorsHandlerMixin from ...common.utils import bytes_ +from ...common.types import RePattern if TYPE_CHECKING: # pragma: no cover @@ -147,7 +147,7 @@ def routes(self) -> List[Union[str, Tuple[str, List[bytes]]]]: must return the url to serve.""" raise NotImplementedError() # pragma: no cover - def handle_route(self, request: HttpParser, pattern: re.Pattern[Any]) -> Url: + def handle_route(self, request: HttpParser, pattern: RePattern) -> Url: """Implement this method if you have configured dynamic routes.""" pass diff --git a/proxy/plugin/reverse_proxy.py b/proxy/plugin/reverse_proxy.py index 4c5b46700f..bef8de01f2 100644 --- a/proxy/plugin/reverse_proxy.py +++ b/proxy/plugin/reverse_proxy.py @@ -13,12 +13,13 @@ Lua """ import re -from typing import Any, List, Tuple, Union +from typing import List, Tuple, Union from ..http import Url from ..http.parser import HttpParser from ..http.server import ReverseProxyBasePlugin from ..http.exception.base import HttpProtocolException +from ..common.types import RePattern class ReverseProxyPlugin(ReverseProxyBasePlugin): @@ -48,7 +49,7 @@ def routes(self) -> List[Union[str, Tuple[str, List[bytes]]]]: r'/get/(\d+)$', ] - def handle_route(self, request: HttpParser, pattern: re.Pattern[Any]) -> Url: + def handle_route(self, request: HttpParser, pattern: RePattern) -> Url: """For our example dynamic route, we want to simply convert any incoming request to "/get/1" into "/get?id=1" when serving from upstream. """ From da46cce060f95344f85bf850f84f34a615a31c7e Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sat, 11 Jun 2022 16:59:32 +0000 Subject: [PATCH 6/8] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- proxy/common/types.py | 2 +- proxy/http/server/plugin.py | 2 +- proxy/plugin/reverse_proxy.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/proxy/common/types.py b/proxy/common/types.py index 5d88c6a0d2..9116f4d742 100644 --- a/proxy/common/types.py +++ b/proxy/common/types.py @@ -10,10 +10,10 @@ """ import re import ssl +import sys import queue import socket import ipaddress -import sys from typing import TYPE_CHECKING, Any, Dict, List, Tuple, Union diff --git a/proxy/http/server/plugin.py b/proxy/http/server/plugin.py index 0f2cb0171a..4e290178f4 100644 --- a/proxy/http/server/plugin.py +++ b/proxy/http/server/plugin.py @@ -20,8 +20,8 @@ from ..connection import HttpClientConnection from ...core.event import EventQueue from ..descriptors import DescriptorsHandlerMixin -from ...common.utils import bytes_ from ...common.types import RePattern +from ...common.utils import bytes_ if TYPE_CHECKING: # pragma: no cover diff --git a/proxy/plugin/reverse_proxy.py b/proxy/plugin/reverse_proxy.py index bef8de01f2..5d2530eda1 100644 --- a/proxy/plugin/reverse_proxy.py +++ b/proxy/plugin/reverse_proxy.py @@ -18,8 +18,8 @@ from ..http import Url from ..http.parser import HttpParser from ..http.server import ReverseProxyBasePlugin -from ..http.exception.base import HttpProtocolException from ..common.types import RePattern +from ..http.exception.base import HttpProtocolException class ReverseProxyPlugin(ReverseProxyBasePlugin): From 93f129ddfdc4d2bbb9099d4ce4579883a8b439db Mon Sep 17 00:00:00 2001 From: Abhinav Singh Date: Sat, 11 Jun 2022 22:36:51 +0530 Subject: [PATCH 7/8] Py3.8 also doesnt allow subscriptable pattern type --- proxy/common/types.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proxy/common/types.py b/proxy/common/types.py index 5d88c6a0d2..900c993cc9 100644 --- a/proxy/common/types.py +++ b/proxy/common/types.py @@ -35,7 +35,7 @@ if sys.version_info.minor == 6: RePattern = Any -elif sys.version_info.minor == 7: +elif sys.version_info.minor in (7, 8): RePattern = re.Pattern # type: ignore else: RePattern = re.Pattern[Any] # type: ignore From 7d68902561d4848fe7e749cae8faa1e81fdcaaad Mon Sep 17 00:00:00 2001 From: Abhinav Singh Date: Sat, 11 Jun 2022 22:44:08 +0530 Subject: [PATCH 8/8] Remove debug print --- proxy/http/server/reverse.py | 1 - 1 file changed, 1 deletion(-) diff --git a/proxy/http/server/reverse.py b/proxy/http/server/reverse.py index e5aa8185a3..63bd3d6537 100644 --- a/proxy/http/server/reverse.py +++ b/proxy/http/server/reverse.py @@ -71,7 +71,6 @@ def handle_request(self, request: HttpParser) -> None: break else: raise ValueError('Invalid route') - print(self.choice) assert self.choice and self.choice.hostname port = self.choice.port or \ DEFAULT_HTTP_PORT \