From 08fc8302cfaf1669c6a13fc44b4d4b68e80c4e61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Bjerregaard=20Vrist?= Date: Sun, 9 May 2021 11:49:19 +0200 Subject: [PATCH] Add lookahead for ip check in AnyUrl (#2512) --- changes/2512-sbv-csis.md | 2 ++ pydantic/networks.py | 4 ++-- tests/test_networks.py | 12 ++++++++++++ 3 files changed, 16 insertions(+), 2 deletions(-) create mode 100644 changes/2512-sbv-csis.md diff --git a/changes/2512-sbv-csis.md b/changes/2512-sbv-csis.md new file mode 100644 index 0000000..944b15e --- /dev/null +++ b/changes/2512-sbv-csis.md @@ -0,0 +1,2 @@ +Add lookahead to ip regexes for `AnyUrl` hosts. This allows urls with DNS labels +looking like IPs to validate as they are perfectly valid host names. diff --git a/pydantic/networks.py b/pydantic/networks.py index edace1f..090b4fb 100644 --- a/pydantic/networks.py +++ b/pydantic/networks.py @@ -69,8 +69,8 @@ def url_regex() -> Pattern[str]: r'(?:(?P[a-z][a-z0-9+\-.]+)://)?' # scheme https://tools.ietf.org/html/rfc3986#appendix-A r'(?:(?P[^\s:/]*)(?::(?P[^\s/]*))?@)?' # user info r'(?:' - r'(?P(?:\d{1,3}\.){3}\d{1,3})|' # ipv4 - r'(?P\[[A-F0-9]*:[A-F0-9:]+\])|' # ipv6 + r'(?P(?:\d{1,3}\.){3}\d{1,3})(?=$|[/:#?])|' # ipv4 + r'(?P\[[A-F0-9]*:[A-F0-9:]+\])(?=$|[/:#?])|' # ipv6 r'(?P[^\s/:?#]+)' # domain, validation occurs later r')?' r'(?::(?P\d+))?' # port diff --git a/tests/test_networks.py b/tests/test_networks.py index 79dfb41..cf681b2 100644 --- a/tests/test_networks.py +++ b/tests/test_networks.py @@ -51,6 +51,8 @@ except ImportError: AnyUrl('https://example.com', scheme='https', host='example.com'), 'https://exam_ple.com/', 'http://twitter.com/@handle/', + 'http://11.11.11.11.example.com/action', + 'http://abc.11.11.11.11.example.com/action', ], ) def test_any_url_success(value): @@ -159,6 +161,16 @@ def test_ipv4_port(): assert url.password is None +def test_ipv4_no_port(): + url = validate_url('ftp://123.45.67.8') + assert url.scheme == 'ftp' + assert url.host == '123.45.67.8' + assert url.host_type == 'ipv4' + assert url.port is None + assert url.user is None + assert url.password is None + + def test_ipv6_port(): url = validate_url('wss://[2001:db8::ff00:42]:8329') assert url.scheme == 'wss'