From 0750b62612f37aee6c86c2da5747f2f45207487f Mon Sep 17 00:00:00 2001 From: ANIS <119749586+assinscreedFC@users.noreply.github.com> Date: Fri, 5 Jun 2026 19:30:49 +0200 Subject: [PATCH] Accept trailing dot on simple hostnames with rfc_1034 hostname('ie', rfc_1034=True) is valid, but hostname('ie.', rfc_1034=True) was rejected. The RFC 1034 trailing dot was only handled by domain() (for dotted names); a simple, single-label hostname went through _simple_hostname_regex(), which does not allow a trailing dot, so it failed. Strip an optional trailing dot before the simple-hostname check when rfc_1034 is set, so a single-label hostname behaves consistently with and without the dot. The dot is still rejected when rfc_1034 is False. Refs #442 --- src/validators/hostname.py | 13 +++++++++++-- tests/test_hostname.py | 5 +++++ 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/src/validators/hostname.py b/src/validators/hostname.py index bdf6bdb0..96fca00f 100644 --- a/src/validators/hostname.py +++ b/src/validators/hostname.py @@ -113,16 +113,25 @@ def hostname( if not value: return False + def _matches_simple_hostname(host: str): + if not maybe_simple: + return False + # A trailing dot (RFC 1034) is also valid on a simple, single-label + # hostname, not only on the dotted names handled by `domain()`. + if rfc_1034 and host.endswith("."): + host = host[:-1] + return _simple_hostname_regex().match(host) + if may_have_port and (host_seg := _port_validator(value)): return ( - (_simple_hostname_regex().match(host_seg) if maybe_simple else False) + _matches_simple_hostname(host_seg) or domain(host_seg, consider_tld=consider_tld, rfc_1034=rfc_1034, rfc_2782=rfc_2782) or (False if skip_ipv4_addr else ipv4(host_seg, cidr=False, private=private)) or (False if skip_ipv6_addr else ipv6(host_seg, cidr=False)) ) return ( - (_simple_hostname_regex().match(value) if maybe_simple else False) + _matches_simple_hostname(value) or domain(value, consider_tld=consider_tld, rfc_1034=rfc_1034, rfc_2782=rfc_2782) or (False if skip_ipv4_addr else ipv4(value, cidr=False, private=private)) or (False if skip_ipv6_addr else ipv6(value, cidr=False)) diff --git a/tests/test_hostname.py b/tests/test_hostname.py index 6ff40406..b28e8044 100644 --- a/tests/test_hostname.py +++ b/tests/test_hostname.py @@ -15,6 +15,9 @@ ("this-pc", False, False), ("lab-01a-notebook:404", False, False), ("4-oh-4", False, False), + # simple, single-label hostname w/ trailing dot (RFC 1034); see #442 + ("this-pc.", True, False), + ("ie.", True, False), # hostname w/ optional ports ("example.com:4444", False, False), ("kräuter.com.", True, False), @@ -45,6 +48,8 @@ def test_returns_true_on_valid_hostname(value: str, rfc_1034: bool, rfc_2782: bo ("this-pc-is-sh*t", False, False), ("lab-01a-note._com_.com:404", False, False), ("4-oh-4:@.com", False, False), + # trailing dot is only allowed with rfc_1034; see #442 + ("this-pc.", False, False), # bad (hostname w/ optional ports) ("example.com:-4444", False, False), ("xn----gtbspbbmkef.xn--p1ai:65538", False, False),