验证主机名字符串
接着之前关于匹配主机名或IP地址的正则表达式的问题,以及参考有效主机名的限制,在Python中,有什么最简单易读、又简洁的方法来匹配或验证主机名/完全合格域名(fqdn)呢?我在下面分享了我的尝试,欢迎大家提出改进意见。
9 个回答
7
根据The Old New Thing的说法,DNS名称的最大长度是253个字符。(实际上可以有255个字节,但其中2个字节是用来编码的。)
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('.'))
有人可能会争论是否应该接受空的域名,这要看具体的目的是什么。
13
这里有一个更严格的版本,参考了Tim Pietzcker的回答,并做了以下改进:
- 将主机名的长度限制为253个字符(去掉可选的结尾点后计算)。
- 字符集限制为ASCII字符(也就是说,使用
[0-9]
而不是\d
)。 - 检查顶级域名(TLD)不能全是数字。
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)
58
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("."))
确保每个部分
- 至少包含一个字符,最多可以有63个字符
- 只能由允许的字符组成
- 不能以连字符开头或结尾。
它还避免使用双重否定(比如not disallowed
),如果hostname
以一个.
结尾,那也是可以的。不过,如果hostname
以多个点结尾,那就会出错(而且应该出错)。