Description
Let me explain what I understand from the reverse proxy plugin and the reverse proxy implementation.
From the plugin: https://github.com/abhinavsingh/proxy.py/blob/develop/proxy/plugin/reverse_proxy.py#L16-L26. The code above is directing /get to httpbin.org/get either on http or https.
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',
]
If I would decide to change the reverse proxy location so everything going through the proxy is matched like this:
REVERSE_PROXY_LOCATION: str = r'/(.*)$'
Now everything(i.e. /get, /post/, /abcddfd/fd/dfd/33/3423432, etc...) will be matched by the proxy but will be dispatched to a fixed string in the REVERSE_PROXY_PASS
array.
This is clear in when the reverse proxy is handling the request: https://github.com/abhinavsingh/proxy.py/blob/develop/proxy/http/server/reverse.py#L65-L71.
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]), # <==== RIGHT HERE, this is a string and that's it
)
break
assert self.choice and self.choice.hostname
port = self.choice.port or \
DEFAULT_HTTP_PORT \
if self.choice.scheme == b'http' \
else DEFAULT_HTTPS_PORT
self.initialize_upstream(text_(self.choice.hostname), port)
My case is to create a reverse proxy that matches a regular expression and upstreams to a dynamic url, where matches from the solved pattern could be added to url.
If I would like to have a way to inject what was resolved from the pattern r'/(.*)$'
, or any other pattern, to the self.reverse[route] in order to have something like:
REVERSE_PROXY_LOCATION: str = r'/(.*)$'
REVERSE_PROXY_PASS = [
b'http://localhost:8090/{1}',
]
# or
REVERSE_PROXY_PASS = [
b'http://localhost:8090/{match}',
]
# Could be another pattern, those are just ideas.
I cannot see a solution for that right now.
The approach of adding patterns will add complexity to the code but it will remove complexity from the developer's plugin.
Another solution would be adding a call from the ReverseProxyBasePlugin
to resolve the self.choice = Url.from_bytes...
and give us the solved location with the pattern and self.reverse[route]
, we just override this method and things and return the magic.
Currently we have no way to get into the handle request inside the ReverseProxy
, added by the --enable-reverse-proxy option. If we have an option to provide what ReverseProxy to be used, that could be another solution to this problem.
Please let me know if this issue can be solved by the current code and if I'm missing something.
Could you help me with this issue?