From 0cb342aef4c8cfd8a7287f800dc9a3487b1360ca Mon Sep 17 00:00:00 2001 From: Adam Hopkins Date: Fri, 25 Mar 2022 00:22:12 +0200 Subject: [PATCH] Better exception for bad URL parse (#2415) --- sanic/exceptions.py | 4 ++++ sanic/request.py | 9 ++++++--- tests/test_request.py | 15 +++++++++++++++ 3 files changed, 25 insertions(+), 3 deletions(-) diff --git a/sanic/exceptions.py b/sanic/exceptions.py index d3bd2613b7..7d9da08308 100644 --- a/sanic/exceptions.py +++ b/sanic/exceptions.py @@ -51,6 +51,10 @@ class InvalidUsage(SanicException): quiet = True +class BadURL(InvalidUsage): + ... + + class MethodNotSupported(SanicException): """ **Status**: 405 Method Not Allowed diff --git a/sanic/request.py b/sanic/request.py index 4e3510e5ab..5f0de3625f 100644 --- a/sanic/request.py +++ b/sanic/request.py @@ -30,10 +30,11 @@ from urllib.parse import parse_qs, parse_qsl, unquote, urlunparse from httptools import parse_url # type: ignore +from httptools.parser.errors import HttpParserInvalidURLError # type: ignore from sanic.compat import CancelledErrors, Header from sanic.constants import DEFAULT_HTTP_CONTENT_TYPE -from sanic.exceptions import InvalidUsage, ServerError +from sanic.exceptions import BadURL, InvalidUsage, ServerError from sanic.headers import ( AcceptContainer, Options, @@ -129,8 +130,10 @@ def __init__( ): self.raw_url = url_bytes - # TODO: Content-Encoding detection - self._parsed_url = parse_url(url_bytes) + try: + self._parsed_url = parse_url(url_bytes) + except HttpParserInvalidURLError: + raise BadURL(f"Bad URL: {url_bytes.decode()}") self._id: Optional[Union[uuid.UUID, str, int]] = None self._name: Optional[str] = None self.app = app diff --git a/tests/test_request.py b/tests/test_request.py index ca2c1e4a75..8de22df1d8 100644 --- a/tests/test_request.py +++ b/tests/test_request.py @@ -4,6 +4,7 @@ import pytest from sanic import Sanic, response +from sanic.exceptions import BadURL from sanic.request import Request, uuid from sanic.server import HttpProtocol @@ -176,3 +177,17 @@ async def get(request): "text/x-dvi; q=0.8", "text/plain; q=0.5", ] + + +def test_bad_url_parse(): + message = "Bad URL: my.redacted-domain.com:443" + with pytest.raises(BadURL, match=message): + Request( + b"my.redacted-domain.com:443", + Mock(), + Mock(), + Mock(), + Mock(), + Mock(), + Mock(), + )