web-dev-qa-db-ja.com

ホスト名文字列を検証する

ホスト名またはIPアドレスに一致する正規表現 をたどって、参照として 有効なホスト名の制限 を使用して、 Pythonのホスト名/ fqdn(完全修飾ドメイン名)?私は以下の私の試みで答えました、改善は歓迎します。

25
kostmo
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("."))

各セグメントが

  • 1文字以上63文字以下
  • 許可された文字のみで構成されています
  • ハイフンで開始または終了しない。

また、二重否定(not disallowed)も回避され、hostname.で終わる場合も問題ありません。 hostnameが複数のドットで終わっている場合は失敗します(そして失敗するはずです)。

49
Tim Pietzcker

The Old New Thing によると、DNS名の最大長は253文字です。 (1つは最大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('.'))

目的に応じて、空のドメイン名を受け入れるかどうかを主張できます。

5
solidsnack

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)
5
Eugene Yarmash
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))
1
imbolc

私はTim Pietzckerの答えの完全性が好きですが、読みやすくするために、正規表現からロジックの一部をオフロードすることを好みます。正直なところ、私はそれらの意味を調べなければなりませんでした(?「拡張子表記」パーツ。さらに、「ダブルネガティブ」アプローチは、正規表現の責任が無効な文字を見つけることだけに制限されるという点で、より明白だと思います。 re.IGNORECASEを使用すると、正規表現を短くできるので気に入っています。

これが別のショットです。長いですが、散文のようなものです。 「可読」は「簡潔」とは少し矛盾していると思います。これまでにスレッドで述べた検証の制約はすべてカバーされていると思います。


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("."))
1
kostmo

私はこの正規表現がPythonで役立つと思います: '^([a-zA-Z0-9] +(\。| \-))* [a-zA-Z0-9] + $'

0
Shubham

車輪を再発明しないでください。ライブラリを使用できます。バリデータ。または、コピーできます そのコード

Installation

pip install validators

使用法

import validators
if validators.domain('example.com')
    print('this domain is valid')
0
toto_tico

この純粋な正規表現は、すべてのパラメーターを満たす必要があります:^(?=.{1,253}\.?$)(?!-)[A-Za-z0-9\-]{1,63}(\.[A-Za-z0-9\-]{1,63})*\.?(?<!-)$

0
Steve Goossens

@TimPietzckerの回答を無料で。 アンダースコア は有効なホスト名文字です(ただしドメイン名には使用できません)。 IDN punycodeドメイン(xn--など)の場合、ダブルダッシュが一般的です。ポート番号を取り除く必要があります。これはコードのクリーンアップです。

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 )
0
mootmoot