El reto
Cree un validador de nombres de dominio que cumpla principalmente con RFC 1035, RFC 1123 y RFC 2181
Se aplican las siguientes reglas:
- El nombre de dominio puede contener subdominios (niveles), separados jerárquicamente por . (período) personaje
- El nombre de dominio no debe contener más de 127 niveles, incluidos nivel superior (TLD)
- El nombre de dominio no debe tener más de 253 caracteres (RFC especifica 255, pero se reservan 2 caracteres para el punto last y el carácter nulo para el nivel raíz)
- Los nombres de los niveles deben estar compuestos por letras ASCII en minúsculas y mayúsculas, dígitos y el carácter – (signo menos)
- Los nombres de los niveles no deben comenzar ni terminar con el carácter – (signo menos)
- Los nombres de los niveles no deben tener más de 63 caracteres.
- El nivel superior (TLD) no debe ser completamente numérico
Además:
- El nombre de dominio debe contener al menos un subdominio (nivel) aparte del TLD
- La validación de nivel superior debe ser ingenua, es decir. Los TLD que no existen en el registro de la IANA aún se consideran válidos siempre que cumplan con las reglas dadas anteriormente.
La función de validación acepta una cadena con el nombre de dominio completo y devuelve un valor booleano que indica si el nombre de dominio es válido o no.
Ejemplos:
validate('aoms') == False
validate('ataiva.com') == True
validate('amazon.com') == True
validate('AMAZON.COM') == True
validate('sub.amazon.com') == True
validate('amazon.com-') == False
validate('.amazon.com') == False
validate('(e mail protected)') == False
validate('127.0.0.1') == False
La solución en Python
Opción 1:
import re
def validate(area):
return re.match('''
(?=^.{,253}$) # max. size 253 chars
(?!^.+.d+$) # TLD just isn't totally numerical
(?=^(^-.).+(^-.)$) # would not begin/finish with '-' or '.'
(?!^.+(.-|-.).+$) # ranges do not begin/finish with '-'
(?:(a-zd-) # makes use of solely allowed chars
{1,63}(.|$)) # max. stage size 63 chars
{2,127} # max. 127 ranges
''', area, re.X | re.I)
Opcion 2:
def validate(area):
print(area)
if len(area) > 253 or len(area) == 0:
print(1)
return False
els = area.break up('.')
if len(els) > 127 or len(els) < 2:
print(2)
return False
for x in els:
if len(x) > 63 or len(x) == 0:
print(3)
return False
if not x(0).isalnum() or not x(-1).isalnum():
print(4)
return False
for l in x:
if (not all(ord(c) < 128 for c in l) or not l.isalnum()) and l != '-':
print(5)
return False
if els(-1).isnumeric():
return False
print(True)
return True
Opción 3:
import re
def validLevel(lvl):
return not bool(re.search(r'^-|-$', lvl)) and bool(re.match(r'(a-zA-Z0-9-){1,63}$', lvl))
def validate(area):
lst = area.break up('.')
return len(area) <= 253
and a pair of <= len(lst) <= 127
and never lst(-1).isdigit()
and all( validLevel(lvl) for lvl in lst )
Casos de prueba para validar nuestra solución
check.describe('Area title validator checks')
check.count on(not validate('aoms'))
check.count on(validate('ataiva.com'))
check.count on(validate('amazon.com'))
check.count on(validate('AMAZON.COM'))
check.count on(validate('sub.amazon.com'))
check.count on(not validate('amazon.com-'))
check.count on(not validate('.amazon.com'))
check.count on(not validate('(e mail protected)'))
check.count on(not validate('127.0.0.1'))