どの文字がURLを無効にしますか?
これらの有効なURLはありますか?
example.com/file[/].html
http://example.com/file[/].html
いくつかの明確化を加えてそして直接上記の問題に取り組むために、URLとURIのために問題を引き起こす文字のいくつかのクラスがあります。
許可されておらず、URL/URIに含まれてはならない文字、予約文字(後述)、および問題を引き起こす可能性のある他の文字がありますが、これらは「不適切」または「安全でない」とマークされます。文字が制限されている理由の説明は、 RFC-1738 (URL)および RFC-2396 (URI)に明確に記載されています。新しい RFC-3986 (RFC-1738への更新)は、与えられた文脈で許される文字の構造を定義していますが、古い仕様は以下の規則でどの文字が許されないかのより単純でより一般的な説明を提供します。
URI構文内で許可されていない除外されたUS-ASCII文字:
control = <US-ASCII coded characters 00-1F and 7F hexadecimal>
space = <US-ASCII coded character 20 hexadecimal>
delims = "<" | ">" | "#" | "%" | <">
フラグメント識別子からURIを区切るために使用されるため、文字「#」は除外されます。パーセント文字 "%"は、エスケープ文字のエンコードに使用されるため、除外されています。つまり、「#」と「%」は特定のコンテキストで使用する必要がある予約文字です。
不適切な文字のリストは許可されますが、問題を引き起こす可能性があります。
unwise = "{" | "}" | "|" | "\" | "^" | "[" | "]" | "`"
クエリコンポーネント内で 予約済み であり、かつ/またはURI/URL内で特別な意味を持つ文字。
reserved = ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" | "$" | ","
上記の「予約済み」構文クラスは、URI内では許可されていますが、汎用URI構文の特定のコンポーネント内では許可されていない可能性がある文字を指します。 "reserved"セットの文字は、すべてのコンテキストで予約されているわけではありません 。たとえば、ホスト名にはオプションのユーザー名を含めることができるので、 '@'文字が特別な意味を持つftp://user@hostname/
のようなものになります。
無効で不適切な文字(例: '$'、 '['、 ']')があり、正しくエンコードする必要があるURLの例を次に示します。
http://mw1.google.com/mw-earth-vectordb/kml-samples/gp/seattle/gigapxl/$[level]/r$[y]_c$[x].jpg
URI/URLの文字制限のいくつかはプログラミング言語に依存しています。たとえば、 '|' (0x7C)文字は、URI仕様で "unwise"としてマークされているだけですが、Java Java.net.URIコンストラクタではURISyntaxExceptionをスローするので、http://api.google.com/q?exp=a|b
のようなURLは許可されずURIオブジェクトインスタンスでJavaを使用する場合は、代わりにhttp://api.google.com/q?exp=a%7Cb
としてエンコードしてください。
ここにある既存の回答のほとんどは、次のようなアドレスの実際の使用を完全に無視しているため、実用的ではありません。
最初に、用語の脱線?これらのアドレスは何ですか?有効なURLですか?
歴史的に、答えは「いいえ」でした。 RFC 3986 によると、2005年から、そのようなアドレスはURIではありません(したがって、URLはURLではありません RIの一種 )。 2005 IETF標準の用語では、 RFC 3987 で定義されているように、IRI(Internationalized Resource Identifiers)を適切に呼び出す必要があります。これは技術的にはURIではありません。 IRIの非ASCII文字。
現代の仕様では、答えは「はい」です。 WHATWG Living Standard は、以前は「URI」または「IRI」と呼ばれていたすべてを単に「URL」として分類します。これは、仕様の用語を、仕様を読んでいない普通の人々が、仕様の goals の1つである「URL」という単語をどのように使用するかに合わせています。
「URL」のこの新しい意味では、どの文字が許可されますか?クエリ文字列やパスなど、URLの多くの部分で、任意の "URL units" を使用できます。
RLコードポイント および パーセントエンコードされたバイト 。
「URLコードポイント」とは何ですか?
URLコードポイントは、ASCII英数字、U + 0021(!)、U + 0024($)、U + 0026( &)、U + 0027( ')、U + 0028左頭頂部、U + 0029右頭頂部、U + 002A(*)、U + 002B(+)、U + 002C(、)、U + 002D(-)、 U + 002E(。)、U + 002F(/)、U + 003A(:)、U + 003B(;)、U + 003D(=)、U + 003F(?)、U + 0040(@)、U + 005F(_)、U + 007E(〜)、およびサロゲートと非文字を除くU + 00A0〜U + 10FFFDの範囲のコードポイント。
(「URLコードポイント」のリストには%
は含まれませんが、%
sは、パーセントエンコードシーケンスの一部である場合、「URL code units」で許可されます。)
このセットでnotの文字の使用が仕様で許可されている唯一の場所は Host で、IPv6アドレスは[
で囲まれ、 ]
文字。 URLの他のすべての場所では、URLユニットが許可されるか、さらに制限の厳しい文字セットが許可されます。
歴史のために、そしてここの答えのどこか他の部分では詳しく探求されていないので、古い仕様のペアで許可されているかどうかを調べてみましょう。
まず第一に、2種類のRFC 3986 予約文字 があります。
:/?#[]@
、これはRFC 3986で定義されたURIの一般的な構文の一部です!$&'()*+,;=
、これはRFCの一般的な構文の一部ではありませんが、特定のURIスキームの構文コンポーネントとして使用するために予約されています。たとえば、セミコロンとコンマは data URIs の構文の一部として使用され、&
と=
はクエリ文字列のユビキタス?foo=bar&qux=baz
形式の一部として使用されます(これはRFC 3986で指定されています)。上記の予約文字はいずれも、エンコードせずにURIで合法的に使用できます。構文上の目的を果たすために、またはそのような使用が構文上の目的を果たす文字として誤って解釈されない場所のデータのリテラル文字として使用できます。 (たとえば、/
はURLで構文上の意味を持ちますが、クエリ文字列では意味を持たないためdoes n'tであるため、クエリ文字列でエンコードせずに使用できます。)
RFC 3986では、いくつかのunreserved文字も指定しています。これらの文字は、エンコードなしでデータを表すために常に常に使用できます。
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._~
最後に、%
文字自体がパーセントエンコードに使用できます。
これにより、URLにforbiddenである以下のASCII文字のみが表示されます。
"<>\^`{|}
ASCIIの他のすべての文字は、URLで合法的に使用できます。
次に、RFC 3987は、予約されていない文字のセットを次のUnicode文字範囲で拡張します。
%xA0-D7FF / %xF900-FDCF / %xFDF0-FFEF
/ %x10000-1FFFD / %x20000-2FFFD / %x30000-3FFFD
/ %x40000-4FFFD / %x50000-5FFFD / %x60000-6FFFD
/ %x70000-7FFFD / %x80000-8FFFD / %x90000-9FFFD
/ %xA0000-AFFFD / %xB0000-BFFFD / %xC0000-CFFFD
/ %xD0000-DFFFD / %xE1000-EFFFD
古い仕様からのこれらのブロックの選択は、最新のユニコード ブロック定義 ;これはおそらく、RFC 3987が作成されてから10年でブロックが追加されたためです。
最後に、特定の文字列がURLの特定の部分でのみ有効であるため、特定の文字列が有効なURLであるかどうかを認識するには、URLで有効に表示される文字を単に知るだけでは十分ではないことに注意してください。たとえば、予約文字[
および]
は、 http:// [1080 :: 8:800:200C:417A]/foo のようなURLのIPv6リテラルホストの一部として有効です他のコンテキストでは合法であるため、OPのhttp://example.com/file[/].html
の例は違法です。
補足の質問で、www.example.com/file[/].html
が有効なURLかどうかを尋ねました。
URLはURIの一種であり、有効なURIはhttp:
のようなスキームを持たなければならないため、そのURLは無効です( RFC 3986 を参照)。
あなたがhttp://www.example.com/file[/].html
が有効なURLであるかどうか尋ねるつもりならば、角カッコ文字がそこで有効ではないので答えはまだノーです。
角括弧文字は、次の形式でURL用に予約されています。http://[2001:db8:85a3::8a2e:370:7334]/foo/bar
(つまり、ホスト名の代わりにIPv6リテラル)
あなたが問題を完全に理解したいならば、それは慎重にRFC 3986を読む価値があります。
URIで使用できるすべての valid 文字( _ url _ は _ uri _ のタイプ)は RFC 3986 で定義されています。
他のすべての文字は、最初に「URLエンコード」されている限り、URLで使用できます。これには、特定の "コード"(通常、パーセント記号(%)の後に16進数が続く形式)の無効な文字を変更することが含まれます。
このリンク、 HTML URLエンコーディングリファレンス には、無効な文字のエンコーディングの一覧が含まれています。
いくつかのUnicode文字範囲は有効なHTML5 ですが、それでも使用するのはお勧めできません。
例えば、href
のドキュメントは http://www.w3.org/TR/html5/links.html#attr-hyperlink-href と言っています:
A要素とarea要素のhref属性には、スペースで囲まれる可能性がある有効なURLの値を指定する必要があります。
それから、 "有効なURL"の定義は http://url.spec.whatwg.org/ を指します。
RFC 3986とRFC 3987を現代の実装に合わせて、その過程で時代遅れにしてください。
その文書は URL code points を次のように定義しています。
ASCII英数字、 "!"、 "$"、 "&"、 "'"、 "("、 ")"、 "*"、 "+"、 "、"、 " - "、 "。"、 "/" 、 ":"、 ";"、 "="、 "?"、 "@"、 "_"、 "〜"、およびU + 00A0からU + D7FF、U + E000からU + FDCFのコードポイント、U + FDF0からU + FFFD、U + 10000からU + 1FFFD、U + 20000からU + 2FFFD、U + 30000からU + 3FFFD、U + 40000からU + 4FFFD、U + 50000からU + 5FFFD、U + 60000からU + 6FFFD、U + 70000からU + 7FFFD、U + 80000からU + 8FFFD、U + 90000からU + 9FFFD、U + A0000からU + AFFFD、U + B0000からU + BFFFD、U + C0000 U + CFFFD、U + D0000からU + DFFFD、U + E1000からU + EFFFD、U + F0000からU + FFFFD、U + 100000からU + 10FFFD。
「URLコードポイント」という用語は、その文で使用されています。
CがURLコードポイントでなく "%"でもない場合、エラーを解析します。
スキーマ、権限、相対パス、クエリ、フラグメントの状態など、解析アルゴリズムのいくつかの部分では、基本的にURL全体です。
また、バリデータ http://validator.w3.org/ は、"你好"
のようなURLを渡し、スペースのような文字を含むURLは渡しません"a b"
もちろん、Stephen Cが述べたように、それは文字だけではなくコンテキストについてもあります。あなたはアルゴリズム全体を理解しなければなりません。しかし、クラスの "URL code points"がアルゴリズムのキーポイントに使われているので、それがあなたが何が使えるかどうかの良い考えを与えます。
URL内のUnicode文字 も参照してください。
URLを文字列に分割する文字を選択する必要があるので、自分でURLに見つからない文字のリストを作成することにしました。
>>> allowed = "-_.~!*'();:@&=+$,/?%#[]?@ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
>>> from string import printable
>>> ''.join(set(printable).difference(set(allowed)))
'`" <\x0b\n\r\x0c\\\t{^}|>'
そのため、考えられる選択肢は、改行、タブ、スペース、バックスラッシュ、および"<>{}^|
です。スペースか改行で行きます。 :)
実際にはあなたの質問に対する答えではありませんが、URLを検証することは非常に深刻な問題です。それが私の経験です。また、URLをpingして有効な応答が返されるかどうかを確認する方法もありますが、そのような単純な作業には多すぎる可能性があります。
URLを検出するための正規表現は豊富です。Googleit :)