From b6cfb432d4b36c57c7a0a5ff1989bb206c0101aa Mon Sep 17 00:00:00 2001 From: Jovial Joe Jayarson Date: Sun, 31 Mar 2024 08:09:47 +0530 Subject: [PATCH] fix: domain validation is now more consistent across rfcs --- src/validators/domain.py | 23 ++++++++++++++--------- src/validators/utils.py | 2 +- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/src/validators/domain.py b/src/validators/domain.py index c5eea7d4..540234e2 100644 --- a/src/validators/domain.py +++ b/src/validators/domain.py @@ -24,32 +24,37 @@ def domain(value: str, /, *, rfc_1034: bool = False, rfc_2782: bool = False): value: Domain string to validate. rfc_1034: - Allow trailing dot in domain name. + Allows optional trailing dot in the domain name. Ref: [RFC 1034](https://www.rfc-editor.org/rfc/rfc1034). rfc_2782: Domain name is of type service record. + Allows optional underscores in the domain name. Ref: [RFC 2782](https://www.rfc-editor.org/rfc/rfc2782). Returns: (Literal[True]): If `value` is a valid domain name. (ValidationError): If `value` is an invalid domain name. + + Raises: + (UnicodeError): If `value` cannot be encoded into `idna` or decoded into `utf-8`. """ if not value: return False try: return not re.search(r"\s", value) and re.match( # First character of the domain - rf"^(?:[a-zA-Z0-9{'_'if rfc_2782 else ''}]" - # Sub domain + hostname - + rf"(?:[a-zA-Z0-9-{'_'if rfc_2782 else ''}]{{0,61}}" - + rf"[A-Za-z0-9{'_'if rfc_2782 else ''}])?\.)" + rf"^(?:[a-z0-9{r'_?'if rfc_2782 else ''}]" + # Sub-domain + + rf"(?:[a-z0-9-{r'_?'if rfc_2782 else ''}]{{0,61}}" + # Hostname + + rf"[a-z0-9{r'_?'if rfc_2782 else ''}])?\.)" # First 61 characters of the gTLD - + r"+[A-Za-z0-9][A-Za-z0-9-_]{0,61}" + + r"+[a-z0-9][a-z0-9-_]{0,61}" # Last character of the gTLD - + rf"[A-Za-z]{r'.$' if rfc_1034 else r'$'}", + + rf"[a-z]{r'.?$' if rfc_1034 else r'$'}", value.encode("idna").decode("utf-8"), re.IGNORECASE, ) - except UnicodeError: - return False + except UnicodeError as err: + raise UnicodeError(f"Unable to encode/decode {value}") from err diff --git a/src/validators/utils.py b/src/validators/utils.py index 80af7893..639de834 100644 --- a/src/validators/utils.py +++ b/src/validators/utils.py @@ -91,7 +91,7 @@ def wrapper(*args: Any, **kwargs: Any): if func(*args, **kwargs) else ValidationError(func, _func_args_as_dict(func, *args, **kwargs)) ) - except (ValueError, TypeError) as exp: + except (ValueError, TypeError, UnicodeError) as exp: if raise_validation_error: raise ValidationError( func, _func_args_as_dict(func, *args, **kwargs), str(exp)