Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions src/validators/domain.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,6 @@ def domain(
if not value:
return False

if consider_tld and not _IanaTLD.check(value.rstrip(".").rsplit(".", 1)[-1].upper()):
return False

try:
service_record = r"_" if rfc_2782 else ""
trailing_dot = r"\.?$" if rfc_1034 else r"$"
Expand All @@ -88,6 +85,11 @@ def domain(
# ref: RFC 1035, presentation form is limited to 253 characters
return False

# IANA lists IDN TLDs in their ASCII (punycode) form,
# so look up the encoded TLD, not the raw one.
if consider_tld and not _IanaTLD.check(encoded.rstrip(".").rsplit(".", 1)[-1].upper()):
return False

return not re.search(r"\s|__+", value) and re.match(
# First character of the domain
rf"^(?:[a-z0-9{service_record}]"
Expand Down
4 changes: 4 additions & 0 deletions tests/test_domain.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,9 @@ def test_returns_true_on_valid_domain(value: str, rfc_1034: bool, rfc_2782: bool
("example_.com", True, False, True),
("somerandomexample.xn--fiqs8s", True, False, False),
("somerandomexample.onion", True, False, False),
("пример.рф", True, False, False),
("пример.рф.", True, True, False),
("例子.中国", True, False, False),
],
)
def test_returns_true_on_valid_top_level_domain(
Expand Down Expand Up @@ -100,6 +103,7 @@ def test_returns_failed_validation_on_invalid_domain(value: str, rfc_1034: bool,
("_example.#13", True, False, True),
("example_.fo-ul", True, False, True),
("somerandomexample.xn-n-fiqs8s", True, False, False),
("пример.рфы", True, False, False),
],
)
def test_returns_failed_validation_invalid_top_level_domain(
Expand Down
26 changes: 26 additions & 0 deletions tests/test_hostname.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,3 +109,29 @@ def test_returns_true_on_hostname_within_rfc_length_limits(value: str):
def test_returns_failed_validation_on_hostname_beyond_rfc_limits(value: str):
"""Test returns failed validation on hostname beyond RFC limits."""
assert isinstance(hostname(value), ValidationError)


@pytest.mark.parametrize(
"value",
[
"example.com:443",
"xn--e1afmkfd.xn--p1ai",
"пример.рф",
"пример.рф:8080",
],
)
def test_returns_true_on_valid_top_level_domain_hostname(value: str):
"""Test returns true on hostname with a TLD allowed by IANA."""
assert hostname(value, consider_tld=True)


@pytest.mark.parametrize(
"value",
[
"example.flat:443",
"пример.рфы",
],
)
def test_returns_failed_validation_on_invalid_top_level_domain_hostname(value: str):
"""Test returns failed validation on hostname with a TLD not allowed by IANA."""
assert isinstance(hostname(value, consider_tld=True), ValidationError)
26 changes: 26 additions & 0 deletions tests/test_url.py
Original file line number Diff line number Diff line change
Expand Up @@ -232,3 +232,29 @@ def test_returns_failed_validation_on_invalid_private_url(value: str, private: O
def test_returns_string_for_valid_file_url(value: str):
"""Test returns true on valid file url. Ref: RFC 8089."""
assert url(value)


@pytest.mark.parametrize(
"value",
[
"https://example.com/path",
"https://xn--e1afmkfd.xn--p1ai/",
"https://пример.рф/",
"http://例子.中国:8080/index.html",
],
)
def test_returns_true_on_valid_top_level_domain_url(value: str):
"""Test returns true on url with a TLD allowed by IANA."""
assert url(value, consider_tld=True)


@pytest.mark.parametrize(
"value",
[
"https://example.flat/",
"https://пример.рфы/",
],
)
def test_returns_failed_validation_on_invalid_top_level_domain_url(value: str):
"""Test returns failed validation on url with a TLD not allowed by IANA."""
assert isinstance(url(value, consider_tld=True), ValidationError)