Validar una cadena de nombre de host
Siguiendo la expresión regular para que coincida con el nombre de host o la dirección IP? y usando Restricciones sobre nombres de host válidos como referencia, ¿cuál es la forma más legible y concisa de hacer coincidir/validar un nombre de host/fqdn (nombre de dominio completo) en Python? He respondido con mi intento a continuación, mejoras bienvenidas.
9 answers
import re
def is_valid_hostname(hostname):
if len(hostname) > 255:
return False
if hostname[-1] == ".":
hostname = hostname[:-1] # strip exactly one dot from the right, if present
allowed = re.compile("(?!-)[A-Z\d-]{1,63}(?<!-)$", re.IGNORECASE)
return all(allowed.match(x) for x in hostname.split("."))
Asegura que cada segmento
- contiene al menos un carácter y un máximo de 63 caracteres
- consiste solo en caracteres permitidos
- no comienza ni termina con un guion.
También evita los negativos dobles (not disallowed
), y si hostname
termina en un .
, eso también está bien. Fallará (y debería fallar) si hostname
termina en más de un punto.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-10-28 12:42:55
Aquí hay una versión un poco más estricta de La respuesta de Tim Pietzcker con las siguientes mejoras:
- Limite la longitud del nombre de host a 253 caracteres (después de eliminar el punto final opcional).
- Limite el conjunto de caracteres a ASCII (es decir, use
[0-9]
en lugar de\d
). - Compruebe que el TLD no es totalmente numérico.
import re
def is_valid_hostname(hostname):
if hostname[-1] == ".":
# strip exactly one dot from the right, if present
hostname = hostname[:-1]
if len(hostname) > 253:
return False
labels = hostname.split(".")
# the TLD must be not all-numeric
if re.match(r"[0-9]+$", labels[-1]):
return False
allowed = re.compile(r"(?!-)[a-z0-9-]{1,63}(?<!-)$", re.IGNORECASE)
return all(allowed.match(label) for label in labels)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:02:05
Por La Vieja Cosa Nueva, la longitud máxima de un nombre DNS es de 253 caracteres. (Uno está permitido hasta 255 octetos, pero 2 de ellos son consumidos por la codificación.)
import re
def validate_fqdn(dn):
if dn.endswith('.'):
dn = dn[:-1]
if len(dn) < 1 or len(dn) > 253:
return False
ldh_re = re.compile('^[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?$',
re.IGNORECASE)
return all(ldh_re.match(x) for x in dn.split('.'))
Uno podría argumentar a favor de aceptar nombres de dominio vacíos, o no, dependiendo del propósito de uno.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-11-15 02:32:30
Me gusta la minuciosidad de la respuesta de Tim Pietzcker, pero prefiero descargar parte de la lógica de las expresiones regulares para facilitar la lectura. Honestamente, tuve que buscar el significado de esas (?
partes de "notación de extensión". Además, creo que el enfoque "doble negativo" es más obvio en que limita la responsabilidad de la expresión regular a solo encontrar cualquier carácter inválido. Me gusta ese re.IGNORECASE permite acortar la expresión regular.
Así que aquí hay otra oportunidad; es más largo, pero se lee como en prosa. Supongo que " legible "está algo en desacuerdo con"conciso". Creo que todas las restricciones de validación mencionadas en el hilo hasta ahora están cubiertas:
def isValidHostname(hostname):
if len(hostname) > 255:
return False
if hostname.endswith("."): # A single trailing dot is legal
hostname = hostname[:-1] # strip exactly one dot from the right, if present
disallowed = re.compile("[^A-Z\d-]", re.IGNORECASE)
return all( # Split by labels and verify individually
(label and len(label) <= 63 # length is within proper range
and not label.startswith("-") and not label.endswith("-") # no bordering hyphens
and not disallowed.search(label)) # contains only legal characters
for label in hostname.split("."))
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-06-23 19:10:21
def is_valid_host(host):
'''IDN compatible domain validator'''
host = host.encode('idna').lower()
if not hasattr(is_valid_host, '_re'):
import re
is_valid_host._re = re.compile(r'^([0-9a-z][-\w]*[0-9a-z]\.)+[a-z0-9\-]{2,15}$')
return bool(is_valid_host._re.match(host))
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-06-13 11:42:42
Cortesía de la respuesta @TimPietzcker. El guion bajo es un nombre de host válido, doubel dash es común para IDN punycode. El número de puerto debe ser despojado. Esta es la limpieza del código.
import re
def is_valid_hostname(hostname):
if len(hostname) > 255:
return False
hostname = hostname.rstrip(".")
allowed = re.compile("(?!-)[A-Z\d\-\_]{1,63}(?<!-)$", re.IGNORECASE)
return all(allowed.match(x) for x in hostname.split("."))
# convert your unicode hostname to punycode (python 3 )
# Remove the port number from hostname
normalise_host = hostname.encode("idna").decode().split(":")[0]
is_valid_hostanme(normalise_host )
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-04-04 15:22:37
Esta expresión regular pura debe cumplir con todos los parámetros:
^(?=.{1,253}\.?$)(?!-)[A-Za-z0-9\-]{1,63}(\.[A-Za-z0-9\-]{1,63})*\.?(?<!-)$
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-08-29 17:04:51
Procesa cada etiqueta DNS individualmente excluyendo caracteres no válidos y asegurando una longitud distinta de cero.
def isValidHostname(hostname):
disallowed = re.compile("[^a-zA-Z\d\-]")
return all(map(lambda x: len(x) and not disallowed.search(x), hostname.split(".")))
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-03-28 06:16:07
Si está buscando validar el nombre de un host existente, la mejor manera es intentar resolverlo. Nunca escribirás una expresión regular para proporcionar ese nivel de validación.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-03-28 11:51:38