diff options
| author | 2020-04-05 22:41:33 +0100 | |
|---|---|---|
| committer | 2020-04-05 22:41:33 +0100 | |
| commit | 8a3f10e3601d63256f0192d43c389d7e62a3b1b9 (patch) | |
| tree | 7edd502ba37feffa61ef02cf232aca1b5d88f7ac /src/utils | |
| parent | add .send_action utils functions to Server, Channel and User (diff) | |
| signature | ||
handle http redirects ourselves, to prevent redirect to localhost
Diffstat (limited to 'src/utils')
| -rw-r--r-- | src/utils/http.py | 58 |
1 files changed, 44 insertions, 14 deletions
diff --git a/src/utils/http.py b/src/utils/http.py index 9f25b315..1bbc9c07 100644 --- a/src/utils/http.py +++ b/src/utils/http.py @@ -69,6 +69,7 @@ class Request(object): json_body: bool = False allow_redirects: bool = True + check_hostname: bool = False check_content_type: bool = True fallback_encoding: typing.Optional[str] = None content_type: typing.Optional[str] = None @@ -169,24 +170,53 @@ def request(request_obj: typing.Union[str, Request], **kwargs) -> Response: request_obj = Request(request_obj, **kwargs) return _request(request_obj) +class HostNameInvalidError(ValueError): + pass +class TooManyRedirectionsError(Exception): + pass + def _request(request_obj: Request) -> Response: request_obj.validate() + + def _assert_allowed(url: str): + hostname = urllib.parse.urlparse(url).hostname + if hostname is None or not host_permitted(hostname): + raise HostNameInvalidError( + f"hostname {hostname} is not permitted") + def _wrap() -> Response: headers = request_obj.get_headers() - response = requests.request( - request_obj.method, - request_obj.url, - headers=headers, - params=request_obj.get_params, - data=request_obj.get_body(), - allow_redirects=request_obj.allow_redirects, - stream=True, - cookies=request_obj.cookies - ) - response_content = response.raw.read(RESPONSE_MAX, - decode_content=True) - if not response.raw.read(1) == b"": - raise ValueError("Response too large") + + redirect = 0 + current_url = request_obj.url + while True: + if request_obj.check_hostname: + _assert_allowed(current_url) + + response = requests.request( + request_obj.method, + current_url, + headers=headers, + params=request_obj.get_params, + data=request_obj.get_body(), + allow_redirects=False, + stream=True, + cookies=request_obj.cookies + ) + + if response.status_code in [301, 302]: + redirect += 1 + if redirect == 5: + raise TooManyRedirectionsError(f"{redirect} redirects") + else: + current_url = response.headers["location"] + continue + + response_content = response.raw.read(RESPONSE_MAX, + decode_content=True) + if not response.raw.read(1) == b"": + raise ValueError("Response too large") + break headers = utils.CaseInsensitiveDict(dict(response.headers)) our_response = Response(response.status_code, response_content, |
