Studying HTTP > RFC-Translations related HTTP

この文書は、 T. Berners-Lee, R. Fielding, L. Masinter: Uniform Resource Identifier (URI): Generic Syntax (RFC 3986), January 2005. を 橋本英彦 が日本語訳した物です。 この文書の取り扱いについては、[Studying HTTP] の RFC 日本語訳を利用するにあたってに従って下さい。

Network Working Group
Request for Comments: 3986
STD: 66
Updates: 1738
Obsoletes: 2732, 2396, 1808
Category: Standards Track
 T. Berners-Lee
        W3C/MIT
    R. Fielding
   Day Software
    L. Masinter
  Adobe Systems
   January 2005

Uniform Resource Identifier (URI): 一般的構文

この文書の位置付け

この文書は、インターネットコミュニティにおけるインターネット標準化過程プロトコルを規定し、改良のために議論と提案を求めるものである。 このプロトコルの標準化状態と状況については、"Internet Official ProtocolStandards" (STD 1) の最新版を参照していただきたい。 この文書の配布に制限は無い。

著作権表示

Copyright © The Internet Society (2005). All Rights Reserved.

概要

Uniform Resource Identifier (URI) は、抽象的あるいは物理的なリソースを識別するための簡潔な文字列である。 この仕様書は、一般的な URI の構文と相対的形式である URI 参照を解決するための手順を定義し、更にインターネット上での URI の使用のついての指針やセキュリティについての考察を示す。 URI の構文では、全ての妥当な URI の上位集合{superset} である文法を定義し、実装が取り得る全ての識別子についてのスキーム特有な必要条件を知らなくても URI 参照の共通の構成要素{component} を解析する事を可能にする。 この仕様書では各 URI の生成文法は定義しない; それらの作業は各 URI スキームについてのそれぞれの仕様書によって行われる。

目次

1. 導入
1.1. URI の概観
1.1.1. 一般的構文
1.1.2.
1.1.3. URI, URL, URN
1.2. 設計について
1.2.1. 転記性
1.2.2. 相互動作からの識別を分離する
1.2.3. 階層的識別子
1.3. 構文の表記法
2. 文字
2.1. パーセントエンコーディング
2.2. 予約文字
2.3. 非予約文字
2.4. エンコード/デコードする時は
2.5. データを識別する
3. 構文の構成要素
3.1. スキーム
3.2. オーソリティ{Authority}
3.2.1. ユーザ情報
3.2.2. ホスト
3.2.3. ポート
3.3. パス
3.4. クエリ
3.5. フラグメント
4. 使用法
4.1. URI 参照
4.2. 相対的参照
4.3. 絶対 URI
4.4. 同一文書の参照
4.5. 接尾辞参照
5. 参照の解決
5.1. 基底 URI の確立
5.1.1. 本文内に埋め込まれた基底 URI
5.1.2. カプセル化しているエンティティからの基底 URI
5.1.3. 取得される URI からの基底 URI
5.1.4. 基底 URI の初期値
5.2. 相対性の解決
5.2.1. 基底 URI を解析する前に
5.2.2. 参照の変形
5.2.3. パスの併合
5.2.4. ドットセグメントの削除
5.3. 構成要素の再構成
5.4. 参照の解決の例
5.4.1. 通常の例
5.4.2. 特異な例
6. 正規化と比較
6.1. 等価
6.2. 比較の梯子
6.2.1. 単純な文字列の比較
6.2.2. 構文に基づく正規化
6.2.3. スキームに基づく正規化
6.2.4. プロトコルに基づく正規化
7. セキュリティについての考察
7.1. 信頼性と整合性
7.2. 悪意のある構造
7.3. 後置のコード変換{Back-End Transcoding}
7.4. 珍しい IP アドレス形式
7.5. 機密性の高い情報
7.6. 意味論的{Semantic} 攻撃
8. IANA について
9. 謝辞
10. 参照文献
10.1. 規約の一部としての参照
10.2. 情報提供としての参照
A. URI のために収集された ABNF
B. 正規表現による URI 参照の解析
C. 状況内の URI の範囲設定
D. RFC 2396. からの変更点
D.1. 追加点
D.2. 修正点
索引
筆者のアドレス
著作権表示全文

1. 導入

Uniform Resource Identifiers (URI) は、リソースを識別するための単純かつ拡張性のある方法を提供する。 URI 構文とその意味論を扱うこの仕様書は、World-Wide Web グローバル情報利用の先進によって導入された概念に由来し、このような識別子の使用は 1990 年から始まり、これは "Universal Resource Identifiers in WWW" [RFC1630] に記述されている。 URI の構文は、"Functional Recommendations for Internet Resource Locators" [RFC1736] 及び "Functional Requirements for Uniform Resource Names" [RFC1737] 内で明示される推奨を満足するように 設計されている。

この文書は、全ての URI について、単一で、一般的な構文を定義するための "Uniform Resource Locators" [RFC1738] 及び "Relative Uniform Resource Locators" [RFC1808] を取り込んだ、[RFC2396] を廃案にするものである。 また、IPv6 アドレスについての構文を導入した、[RFC2732] を廃案にするものである。 この文書は、RFC 1738 で個々の URL スキーム特有の構文について定義した部分を除外している; これらの部分は、独立した文書として更新されるであろう。 新たな URI スキームの登録についての手順は、[BCP35] によって独立して定義される。 新たな URI スキームの設計者のための助言は、[RFC2718] にて見つけられるだろう。 RFC 2396 からの全ての重要な変更点は、付録 D 内に注記されている。

1.1. URI の概観

URI は、以下のように特徴付けられる:

統一書式 {Uniform}
統一書式性にはいくつかの利点がある。 異なる型のリソース識別子を同じ状況の中で、例えそれらの資源にアクセスするためのメカニズムが異なっていても、使う事ができる。 異なる型のリソース識別子に共通した構文の慣習を、同一の意味論で解釈できる。 既に存在する識別子が使用する方法を妨げる事無く新たな型のリソース識別子を導入できる。 識別子をさまざま異なった状況で再利用でき、それゆえ新たなアプリケーションやプロトコルは既に存在する、巨大で広く用いられているリソース識別子の集合を活用できる。
リソース {Resource}
この仕様書では、リソースであるものの範囲を制限しない; むしろ、"リソース" という用語は、URI によって識別される全てのものについて一般的な意味において使用される。 よく知られた例としては、電子文書、画像、一貫性のある目的をもつ情報源 (例えば、"本日のロサンゼルスの天気予報")、サービス (例えば、HTTP から SMS へのゲートウェイ)、またその他のリソースの集合等がある。 リソースは、インターネットを通じてアクセス可能である必要はない; 例えば、人間、企業、及び図書館にある装丁された書籍も、リソースとみなす事ができる。 同様に、数学の方程式の演算子やオペランド、関係の種類 (例えば、"親" や "会社員")、あるいは数値 (例えば、"0" や "1", "無限大") のような、抽象的な概念もリソースとなりうる。
識別子 {Identifier}
識別子は、識別の範囲内の他の全てのものから特定されている事を区別するために必要な情報を具体化する。 我々は、"識別" や "識別する" という用語を、あるリソースを他の全てのリソースから区別する目的のために用い、その目的がどのように (例えば、氏名、住所、あるいは状況によって) 達成されるかにかかわらない。 これらの用語は、識別子が、いくつかの識別子の場合ではそうでなくても、参照されるものの識別を定義する、あるいは具体化するという事の前提であると誤用されるべきではない。 また、URI を使用するシステムがリソースを識別してアクセスするという事を仮定すべきではない: 多くの場合、URI は、それらがアクセスされるといういかなる意図もなしにリソースを表すために使用される。 同様に、識別される "一つの" リソースは、本質的に唯一である必要はない (例えば、リソースとは、名付けられた一式のもの、あるいは時間経過と共に変化するものへの写像でありうる)。

URI は、Section 3 内の <URI> と名付けられる構文則に一致する文字列から成る識別子である。 また、名付けられるスキーム (Section 3.1) の独立して定義される拡張集合を通じてのリソースの統一書式の識別子も可能である。 その識別がどのように達成され、割り当てられ、あるいはそれを可能にするかは、それぞれのスキームの仕様書に委ねられる。

この仕様書は、アプリケーションが、リソースを識別するための URI を使用して、参照されるリソース、あるいはある種のシステムを探すかもしれないので、リソースの性質においていかなる制限も設けない。 この仕様書は、URI が時を経ても同じリソースを識別し続ける事を、それが全ての URI スキームの共通した目標ではあるけれども、要求はしない。 それにもかかわらず、この仕様書は、アプリケーションがそれ自身を特定のリソースの種類に制限する事や、そのアプリケーションで望まれる特性を保持する URI の部分集合に 制限する事を妨げない。

URI は、世界的規模の範囲を持っており、その解釈の結果はエンドユーザの状況と関連しているかもしれないが、状況にかかわらず一貫して解釈される。 例えば、"http://localhost/" は、その参照の全てのユーザが同じ解釈を持っているが、各エンドユーザにとって "localhost" に対応するネットワークインタフェースは異なる: すなわち、解釈はアクセスに依存しない。 しかし、その参照に基づいて行われた動作はエンドユーザの状況と関連して行われるであろう。 これは、全体において一意なものを参照する意図がある動作では、そのリソースを全ての他のものと区別するような URI を使用しなければならない事を意味する。 エンドユーザのローカルの状況と関連して識別するような URI は、オンラインヘルプマニュアルがエンドユーザのファイルシステム上のファイルを参照する (例えば、"file:///etc/hosts") 時のように、状況自体がリソースの定義している解釈である時のみ使用されるべきである。

1.1.1. 一般的構文

各 URI は Section 3.1 に定義されるように、そのスキームの中にある識別子を割り当てた仕様書を参照するような、スキーム名から始まる。 その場合、URI 構文は各スキームの仕様書がそのスキームを使用する識別子の構文と意味論を更に制限する事ができるような、連結された、拡張可能な命名システムである。

この仕様書は、全ての URI スキームが必要とする、あるいは多くの URI スキームに共通であるような URI 構文の要素を定義する。 従って、ここでは URI 参照のためにスキームに依存しない解析メカニズムを実装するのに必要な構文と意味論を定義し、スキーム依存な URI の扱いはスキーム依存な意味論が必要になるまで先延ばしする事ができる。 同様に、URI 参照を利用するプロトコルやデータ形式は、未だ定義されていないそれらのスキームを含む、全ての URI について認められた構文の範囲のための定義として、この仕様書を参照する事ができる。 これは、識別するスキームの発展と、URI を利用するプロトコル、データ形式、及び実装の発展とを切り離す。

一般的な URI 構文のパーサは、あらゆる URI 参照をその主な構成要素に解析する事ができる。 一度スキームが決定されれば、更にスキーム特有な解析が構成要素上で実行されるであろう。 言い換えれば、URI 一般構文は全ての URI スキームの構文の上位集合である。

1.1.2. 例

以下に例示する URI は、いくつかの URI スキームとそれらの一般的な構文構成要素においての変化を例証したものである。

 ftp://ftp.is.co.za/rfc/rfc1808.txt

 http://www.ietf.org/rfc/rfc2396.txt

 ldap://[2001:db8::7]/c=GB?objectClass?one

 mailto:John.Doe@example.com

 news:comp.infosystems.www.servers.unix

 tel:+1-816-555-1212

 telnet://192.0.2.16:80/

 urn:oasis:names:specification:docbook:dtd:xml:4.1.2

1.1.3. URI, URL, URN

URI は、それが位置指定子か、名前か、あるいはその両方かという点において、更に分類できる。 "Uniform Resource Locator" (URL) という用語は、リソースを識別するのに加えて、その主なアクセスメカニズム (例えば、そのネットワーク上の "位置") を記述する事によってリソースの場所を見つける方法を提供するような、URI の部分集合を指す。 "Uniform Resource Name" (URN) という用語は、例えそのリソースが存在しなくなったり、あるいは利用不可能になっても全体において一意で永続的である事が要求される "urn" スキーム [RFC2141] の下での両方の URI、また名前の特性を持つあらゆる他の URI を参照するために歴史的に使用されている。

個々のスキームは、"名前" あるいは "位置指定子" のどちらか一方に分類される必要はない。 あらゆる与えられたスキームからの URI の例でも、名前、位置指定子、あるいは両方の特性を持っているかもしれないし、これはしばしばスキームのどんな品質よりも、命名の権威{naming authority} による識別子の割り当てにおける永続性と配慮に依存する。 将来の仕様書や関連文書では、より制限された用語である "URL" や "URN" よりも一般的な用語である "URI" を使用すべきである [3305]。

1.2. 設計について

1.2.1. 転記

URI 構文は、その主な考慮事項の一つとして世界的な転記性を持つように設計されている。 URI は、非常に限られた文字集合、すなわち基本的なラテンアルファベット、数字、そしていくつかの特殊文字から成る文字列である。 URI は、例えば、紙の上のインクや、画面上のピクセル、あるいはエンコードしているオクテット文字列中など、様々な方法で表現できる。 URI の解釈は、使用されている文字にのみ依存し、それらの文字がネットワークプロトコル中でどのように表現されているかには依存しない。

転記性の目的は、簡単な筋書きによって説明する事ができる。 ある国際会議で、2 人の参加者 Sam と Kim が、パブで席について、研究のアイデアをやりとりしている様子を想像して頂きたい。 Sam が Kim により詳細な情報を得るための場所を尋ねると、Kim は研究のサイトの URI をナプキンに書く。 家に帰った後、Sam がナプキンを取り出しコンピュータに URI を打ち込めば、Kim が示した情報を取得するであろう。

このシナリオによって、いくつかの設計上の考慮事項が明らかにされている:

これらの設計についての考慮事項は、常に合致するわけではない。 例えば、ある URI 構成要素において最も意味を持つ名前があるシステムではタイプできないような文字を必要とするというような場合がしばしばある。 リソース識別子をあるメディアから別のメディアへ転記するための能力は、URI が最も意味を持つ構成要素から成る事よりも重要であると考えられている。

ローカルや局所的状況において、かつ技術的改良を持ってすれば、ユーザはより広範囲の文字を使用でき、恩恵をうけるかもしれない; 但し、そのような使用法はこの仕様書では定義されない。 Percent-encoded オクテット (Section 2.1) は、その表現がその URI が参照するスキーム、あるいはプロトコル要素によって認められているのであれば、US-ASCII にてコード化された文字セットの範囲外の文字を表すために URI の中で使用する事ができる。 そのような定義は、percent-encode する前に、その文字をオクテットにマッピングするために使用される文字エンコーディングを明示すべきである。

1.2.2. 相互動作からの識別を分離する

URI のについて一般的な誤解は、それらがアクセス可能なリソースを示すためだけに使用されるとされている事である。 URI 自身は、識別を提供するだけである; すなわち、URI の存在によってリソースへのアクセスが保証されてもいないし、意味されるという事でもない。 その代わり、URI 参照に関連するあらゆる操作は、それが表されるプロトコルの要素、データの形式属性、あるいは自然言語文書によって定義される。

URI が与えられた場合、システムは、"アクセス"、"更新"、"置き換え"、あるいは "属性の検索" 等の語によって特徴付けられるような、様々な操作をそのリソースへ行おうとするかもしれない。 そのような操作は、この仕様書によってではなく、URI を利用するプロトコルによって定義される。 しかし、我々は URI における共通の操作について記述するためのいくつかの一般的な用語を使用する。 URI "解決" は、URI を逆参照 {dereference} するために必要なアクセスメカニズムや適切なパラメータを決定するための手順である。 この解決は、数回の繰り返しが必要かもしれない。 URI 上にあるリソースへの動作を実行するためにそのアクセス機構を使用する事が、URI を "逆参照" するという事である。

URI が情報源を特定するために情報取得システムの中で使用される時に、最も一般的な URI 逆参照の形式は "取得{retrieval}" である: すなわち、それに関連したリソースの表現を取得するために URI を利用する。 "表現" とは、表現が生成される時のリソースの状態に関する記録の構成要素であるオクテット列と、それらオクテットを説明するための外部データ表現である。 情報の取得は、ローカルにキャッシュされた表現についてチェックするためのキャッシュ鍵としての URI の使用、(存在する場合) 適切なアクセスメカニズムを決定するための URI の解決、そして取得操作を適用するための URI の逆参照を包括した過程によって成し遂げられる。 取得を実行するために使用されるプロトコルによっては、リソース (リソース外部データ) についてや、他のリソースとの関係についての追加情報が提供されるかもしれない。

情報取得システムにおける URI 参照は、遅延結合{late-binding} であるように設計される: 一般に、アクセスの結果はアクセスされる時に決定されるが、それは時間経過あるいは他の相互作用による状況により変化するかもしれない。 これらの参照は、将来に使用されるために生成されるものである: そこで識別されているものは過去に得られたある特定の結果ではないが、将来の結果において真実であると予測される何らかの特性ではある。 そのような場合、URI によって参照されるリソースは、実際には時を経た後に観測された時には、もしかしたらリソース供給者によって追加コメントや主張による説明がなされているかもしれないが、同一の特性を持つ。

多くの URI スキームがプロトコルにちなんで名付けられているが、これはこれらの URI の使用が名付けられたプロトコルを通じてリソースへアクセスする結果になるという事を意味するものではない。 URI は、しばしば単純なる識別のために使用される。 URI がリソースの表現を取得するために使用される時でさえ、そのアクセスはスキーム名に関連するプロトコルに依存しないゲートウェイ、プロクシ、キャッシュ、及び名前解決サービスを通じてのものかもしれない。 いくつかの URI の解決では複数のプロトコルの使用を必要とするかもしれない (例えば、表現がローカルキャッシュ内に見つけられない時には "http" URI のオリジンサーバへアクセスするために、通常 DNS と HTTP の両方が使用される)。

1.2.3. 階層的識別子

URI 構文は階層的に組織化されており、より重要度が減少していく順に左から右へ構成要素が列挙されている。 いくつかの URI スキームにおいては、可視的階層構造はスキーム自体に制限される: この場合、スキーム要素区切り子 (":") の後の全ては、URI 処理から見られない{opaque} とみなされる。 その他の URI スキームでは、階層構造を一般的な構文解析アルゴリズムに明示かつ可視にする。

一般的構文では、一般的なパーサの識別子の階層的な解釈に重要である構成要素を区切るために、スラッシュ ("/")、疑問符 ("?")、及び番号記号 ("#") 文字を使用する。 命名スキームを超えたこの階層構造の統一的表現は、わかりやすい構文の一貫した使用を通じてそのような識別子の読み易さを助ける事に加えて、スキームに依存しない参照をその階層構造に相対させる事ができる。

文書のグループあるいは "木{tree}" が共通の目的に役立つように構成されており、それら文書の大量の URI 参照がその外よりも木の中のリソースを指すような場合がしばしばある。 同様に、特定のサイトに位置する文書は、リモートサイトにあるリソースよりもはるかに、そのサイトにある他のリソースを参照するであろう。 URI の相対的参照によって、文書木はそれらの位置やアクセススキームに部分的に独立させる事ができる。 例えば、単一のハイパーテキスト文書の集合が相対的参照によってが互いに参照するならば、"file", "http", "ftp" の各スキームでアクセス可能であり、また横断可能{traversable} であるようにする事もできる。 更に、そのような文書木は、相対的参照のいずれも変更せずに、全体で、移動する事ができる。

相対的参照 (Section 4.2) は、参照状況と目標 URI の間の階層的名前空間における違いを記述する事によってリソースを参照する。 Section 5 に示される参照解決アルゴリズムは、そのような参照がどのように目標 URI に変形されるかを定義する。 相対的参照は階層的な URI の状況中でのみ使用されるので、新たな URI スキームの設計者は、そのスキーム中で相対的参照を禁じざるを得ない理由がないのであれば、一般的な構文の階層的構成要素に一致する構文を使用すべきである。

注意: 以前の仕様書では、URI の相対的参照を示すために "部分的 UR" と "相対的 URI" という用語を使用した。 何人かの読者がそれらの用語の意味を相対的な URI とは URI を参照する方法ではなく、URI の部分集合であると誤解したので、この仕様書ではそれらを単に相対的参照と述べる。

全ての URI 参照は、一般的な構文パーサが使用された時に解析される。 しかし、 1 つ以上のドットセグメント (Section 3.3 にて説明されるような、"." や ".." を持つ完全パスセグメント) を含んでいなければ、階層的処理は参照内で使用される絶対 URI には影響を与えないので、URI スキームの仕様は、スラッシュ文字、疑問符文字、及び "scheme:." と "scheme:.." という URI の使用を禁じる事によって、隠された{opaque} 識別子を定義する事ができる。

1.3. 構文の表記法

この仕様書は、[RFC2234] で定義される以下のコア ABNF 構文則を含む、Augmented Backus-Naur Form (ABNF) 表記法を使用する: ALPHA (文字), CR (復帰), DIGIT (10 進数字), DQUOTE (二重引用符), HEXDIG (16 進数字), LF (改行), SP (スペース)。 完全なる URI 構文は、付録 A に纏められる。

2. 文字

URI 構文は、おそらくリソースを識別するために、データを文字列をしてエンコードする方法を提供する。 URI 文字は、順に、転送や表示のためにオクテットに頻繁にエンコードされる。 この仕様書では、それらの文字を保存したり、転送するために使用される URI 文字とオクテットの間のマッピングについていかなる特定の文字エンコーディングも強制しない。 URI がプロトコル要素内に現れる場合、文字エンコーディングはそのプロトコルによって定義される; もしそのような定義がなければ、URI は周囲のテキストと同じ文字エンコーディングであると仮定される。

ABNF 表記法は、その端子の値を US-ASCII にてコード化された文字セット [ASCII] に基づく負でない整数 (codepoints) と定義する。 URI は文字列なので、URI 構文を理解するためにその関係を逆にしなければならない。 従って、ABNF にて使用される整数値は構文則を完成するために US-ASCII を通してその対応する文字へとマッピングし戻さなければならない。

URI は、数字、文字、及びいくつかの図形記号から成る文字の限定的な集合から構成される。 それらの文字のうちの予約されている部分集合は、区切り子としての役目を果たさない予約されていない集合とそれらの予約されている集合を含む、残りの文字が各構成要素の識別データを定義する間、URI 中の構文構成要素を区切るために使用される。

2.1. パーセントエンコーディング

パーセントエンコーディング{percent-encoding} メカニズムは、オクテットの対応する文字が認められた文字の範囲外にある、あるいは構成要素の中で区切り子として使用されている場合に使用される。 パーセントエンコードされたオクテットは、パーセント文字 "%" と、そのオクテットの数値を表している二桁の 16 進数字から成る三重語としてエンコードされる。 例えば、"%20" は 2 進オクテット "00100000" (ABNF: %x20) についてのパーセントエンコーディングであり、US-ASCII のスペース文字 (SP) に対応している。 Section 2.4 は、パーセントエンコーディングとデコーディングが適応される時について記述している。

 pct-encoded = "%" HEXDIG HEXDIG

大文字の 16 進数字 'A' から 'F' は、小文字の 'a' から 'f' とそれぞれ等価である。 二つの URI のパーセントエンコードされたオクテット内で使用される 16 進数字の大文字・小文字のみが異なる場合、それらは等価である。 整合性を持たせるため、URI の生成を行うもの{producers} や正規化を行うもの{normalizers} は全てのパーセントエンコーディングについて大文字の 16 進数字を使用すべきである。

2.2. 予約文字

URI は、"予約されている" 集合内の文字によって区切られる構成要素及び副構成要素を含んでいる。 これらの文字は、URI の逆参照アルゴリズムにおける一般的な構文、各スキーム特有の構文、あるいは実装特有の構文によって区切り子として定義される (あるいはされない) ので、"予約されている" と呼ばれる。 URI 構成要素についてのデータがデリミタとして予約されている文字の目的と競合する場合、競合するデータは URI が形成される前にパーセントエンコーディングされなければならない。

 reserved    = gen-delims / sub-delims

 gen-delims  = ":" / "/" / "?" / "#" / "[" / "]" / "@"

 sub-delims  = "!" / "$" / "&" / "'" / "(" / ")"
             / "*" / "+" / "," / ";" / "="

予約されている文字の目的は、URI 中の他のデータから区別可能である区切り文字の集合を提供する事である。 予約文字を、対応するパーセントエンコードされたオクテットに置き換えている点が異なる URI は、等価ではない。 ほとんどのアプリケーションにおいて、予約文字をパーセントエンコーディングする、あるいは予約文字に対応するパーセントエンコードされたオクテットをデコードする事によって、URI がどう解釈されるかが変わるであろう。 従って、予約されている集合内の文字は正規化{normalization} から保護されており、それ故に、それらは URI 内のデータ副構成要素を区切るためにスキーム特有、あるいは生成を行うもの特有のアルゴリズムによって使用されても安全であるだろう。

予約されている文字の部分集合 (gen-delims) は、Section 3 にて記述されるように一般的な URI 構成要素の区切り子として使用される。 構成要素の ABNF 構文則は、reserved あるいは gen-delims 規則名を直接には使用しないだろう; その代わり、各構文則は、その構成要素として認められる (すなわち、それを区切らない) 文字と、そして予約されている集合の中にも構成要素の中の副構成要素の区切り子としての使用のために "予約されている" 任意の文字を列挙する。 この仕様書では最も一般的な副構成要素のみを定義する; 他の副構成要素は、そのような副構成要素がその構成要素として認められる予約されている集合内によって区切られるのであれば、URI スキームの仕様書、あるいは URI 逆参照アルゴリズムの実装特有な構文にて定義されるであろう。

URI 生成アプリケーションは、もし予約されている集合内の文字がその構成要素内のデータを表すために URI スキームによって特に認められているのでなければ、それらの文字に対応するデータオクテットをパーセントエンコードすべきである。 予約されている文字が URI 構成要素内に見つかったが、その文字についての区切り規則がわからない場合は、US-ASCII 内のその文字エンコーディングに対応するデータオクテットを表すものとして解釈されなければならない。

2.3. 非予約文字

URI 内に含む事が認められており、予約目的のない文字は、予約されていない (unreserved) と呼ばれる。 これは、大文字と小文字のアルファベット、数字、ハイフン、ピリオド、アンダースコア、チルダが含まれる。

 unreserved  = ALPHA / DIGIT / "-" / "." / "_" / "~"

非予約文字を、対応するパーセントエンコードされた US-ASCII オクテットに置き換えている点が異なる URI は、等価である: それらは同じリソースを識別する。 しかし、URI 比較を行う実装が常に比較の前に正規化を行うわけではない (Section 6 参照)。 整合性を持たせるため、URI の生成を行うものは ALPHA (%41-%5A と %61-%7A), DIGIT (%30-%39), hyphen (%2D), period (%2E), underscore (%5F), tilde (%7E) の範囲におけるパーセントエンコードされたオクテットを生成すべきではないし、URI を発見した時に、URI 正規化によってそれらを対応する非予約文字にデコードすべきである。

2.4. エンコード/デコードする時は

通常の状況下では、URI 内のオクテットがパーセントエンコードされる時は、その構成部品から URI の生成処理の間のみである。 これは、実装が副構成要素の区切り子として予約文字のいずれを使用するか、そしてそれはデータとして安全に使用できるを決定する時である。 一度生成されれば、URI は常にパーセントエンコードされた形式である。

URI が逆参照される時、スキーム特有の逆参照処理 (存在する場合) に重要である構成要素と副構成要素は、そうしなければデータが構成要素の区切り子と間違えられるので、それらの構成要素に含まれるパーセントエンコードされたオクテットが安全にデコードされる前に解析され、分割されなければならない。 唯一の例外は、パーセントエンコードされたオクテットが非予約集合内の文字に対応する場合で、この時はいつでもデコードできる。 例えば、チルダ ("~") に対応するオクテットは、古い URI 処理実装によってしばしば "%7E" としてエンコードされる; しかし、 "%7E" はその解釈を変える事無く "~" に置き換える事ができる。

パーセント ("%") 文字はパーセントエンコードコード化されたオクテットのための指示器{indicator} としての役割を持つので、そのオクテットを URI 内のデータとして使用するためには"%25" とパーセントエンコードされなければならない。 既にデコードされた文字列を更にデコーディングする事はパーセントデータオクテットをパーセントエンコーディングの始まりと誤解する事に繋がるし、逆にパーセントエンコーディングの場合も既にエンコードされた文字列を誤解する事に繋がるであろうから、実装は同じ文字列を複数回パーセントエンコードやパーセントデコードをしてはならない。

2.5. データを識別する

URI 文字は、各 URI 構成要素についてデータの識別を提供し、システム間の識別のための外部インタフェースとしての役目を持つ。 URI 生成インタフェースの存在と性質は URI を使用するクライアントから隠される (そしてそれ故この仕様書で定義される相互運用性要件の範囲を超える) が、これは URI 文字の解釈の問題における頻繁な混乱と誤りの原因である。 実装者は、URI の生成と送信において複数の文字エンコーディング、すなわち、ローカル名、データエンコーディング、パブリックインタフェースエンコーディング、URI 文字エンコーディング、データフォーマットエンコーディング、プロトコルエンコーディングがある事に気付いていなければならない。

ファイルシステム名のようなローカル名は、ローカルな文字エンコーディングを用いて保存される。 URI 生成アプリケーション (例えば、オリジンサーバ) は、通常意味のある名前を生成するために原則としてローカルなエンコーディングを使用するであろう。 URI 生成者は、ローカルのエンコーディングをパブリックインタフェースに適するものに変形し、URI 文字の制限される集合 (予約文字、非予約文字、パーセントエンコーディング) へとパブリックインタフェースエンコーディングを変形するであろう。 それらの文字はデータフォーマットに含まれる参照として使用されるオクテット (例えば、文書の文字セット) として、順にエンコードされ、そのようなデータフォーマットは、しばしば続いてインターネットプロトコルを通じた転送のためにエンコードされます。

ほとんどのシステムにおいて、URI 構成要素内に現れる非予約文字は、US-ASCII 内のその文字のエンコーディングに対応するデータオクテットを表すものとして解釈される。 URI の需要者{Consumer} は、文字 "X" はオクテット "01011000" に対応すると仮定するし、例えその仮定が正しくない時でさえ、それを行う事において差し支えない。 EBCDIC のように、内部的に異なる文字エンコーディングの形式にて識別を提供するシステムは、一般に内部インタフェースにおいて原文の識別子を UTF-8 [STD63] (あるいはいくつかの US-ASCII 文字エンコーディングの上位集合) へと文字変換エンコーディングを実行し、それにより単に元のオクテットをパーセントエンコードしたものよりもより意味を持つ識別子を提供できるであろう。

例えば、内部的に EBCDIC ベースのファイルシステムを使用して保存し、HTTP サーバを通じてインターネット上のクライアントへデータを提供するような情報サービスを考える。 著者がそのファイルシステム上に "Laguna Beach" という名前のファイルを作成する時、そのリソースに対応する "http" URI は意味を持つ文字列 "Laguna%20Beach" を含むと思われる。 しかし、 そのサーバが極度に単純化した未加工オクテットマッピングを使用して URI を生成した場合、その結果は "%D3%81%87%A4%95%81@%C2%85%81%83%88" を含む URI となるであろう。 内部コード変換インタフェースは、URI を生成する前にそのローカル名を US-ASCII の上位集合にコード変換する事でこの問題を修正する。 当然、そのようなインタフェースにおいて入って来る URI の適切な解釈には、逆コード変換がローカル名を得るために適用される前にパーセントエンコードされたオクテットが (例えば、"%20" から SP へと) デコードされる必要がある。

いくつかの場合では、それを表すために作られている URI 構成要素と識別されるデータの間と内部インタフェースは文字エンコーディングの翻訳よりよっぽど遠回りなものとなる。 例えば、URI の一部では、非 ASCII データにおけるクエリや、地図における数値座標を反射するかもしれない。 同じく、URI スキームは、構成要素を形成し URI を生成する前に、追加的エンコーディング要求を持つ構成要素を定義するかもしれない。

新たな URI スキームが汎用文字セット [UCS] の文字から成るテキストデータを表す構成要素を定義する時、そのデータは最初に [STD63] エンコードする UTF-8 文字によってオクテットとしてエンコードされるべきである; そして、非予約集合内の文字に対応していないオクテットのみをパーセントエンコーディングすべきである。 例えば、文字 A は "A" と、GRAVE (訳注: アクセント記号) を持つラテン語の大文字では "%C3%80" と、カタカナ文字のアは "%E3%82%A2" と、それぞれ表されるであろう。

3. 構文の構成要素

一般的な URI 構文では、scheme, authority, authority, path, query, fragment と呼ばれる構成要素の階層的なシーケンスから成る。

 URI         = scheme ":" hier-part [ "?" query ] [ "#" fragment ]

 hier-part   = "//" authority path-abempty
             / path-absolute
             / path-rootless
             / path-empty

構成要素として scheme と path は必要であるが、path は空 (文字がない) かもしれない。 authority がある場合、path は空であるか、あるいはスラッシュ ("/") 文字で始めなければならない。 authority がない場合、path は 2 つのスラッシュ文字 ("//") で始まる事はできない。 これらの制限は path (Section 3.3) への五つの異なる ABNF 規則をもたらすが、与えられたいかなる URI 参照もその中の一つのみに一致するであろう。

以下は、二つの URI の例とそれらの構成要素部分である:

   foo://example.com:8042/over/there?name=ferret#nose
   \_/   \______________/\_________/ \_________/ \__/
    |           |            |            |        |
 scheme     authority       path        query   fragment
    |   _____________________|__
   / \ /                        \
   urn:example:animal:ferret:nose

3.1. スキーム

各 URI は、そのスキームを含む識別子を割り当てるための仕様書を参照するスキーム名で始まる。 その場合、URI 構文は各スキームの仕様書がそのスキームを使用する識別子の構文と意味論を更に制限する事ができるような、連結された、拡張可能な命名システムである。

スキーム名は、文字で始まり、その後に文字、数字、プラス("+")、ピリオド ("."), ハイフン ("-") を繋げたものから成る。 scheme は大文字・小文字を区別しないが、標準形は小文字なので、scheme を規定する文書では小文字で記述しなければならない。 実装は、ロバスト性のために scheme において大文字を小文字と同等に受け入れる (例えば、"HTTP" を "http" と同様に認める) べきであるが、整合性を持たせるために小文字のスキーム名のみを生成するべきである。

 scheme      = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." )

個々のスキームはこの文書では規定されない。 新たな URI スキームの登録の手順は、[BCP35] によって別個に定義される。 スキームの登録では、スキーム名とそれらの仕様書間の対応を保存する。 新たな URI スキームの設計者への助言は、[RFC2718] にて見つけられる。 URI スキームの仕様は、それらのスキーム特有の構文に合致する全ての文字列が、Section 4.3 にて記述されるように、<absolute-URI> の文法にも合致するように、それら自身の構文も定義しなければならない。

一つ以上のスキーム特有の制限に違反する URI がある場合、スキーム特有の解決処理は不使用の部分を無視するよりもエラーとしてその参照を知らせるべきである; そうする事によって、同等な URI の数を減らし、一般的な構文の乱用を検出する助けとなる。 これはその URI がユーザを誤り導くために構成されている事を示すものかもしれない (Section 7.6)。

3.2. オーソリティ

多くの URI スキームは命名オーソリティ{authority} についての階層的な要素に含んでいるので、URI の残りの部分によって定義される名前空間の管理はそのオーソリティへと委ねられる (それらは更に他へ委ねられるかもしれない)。 一般的な構文は、登録名あるいはサーバアドレス、そして任意のポートとユーザ情報に基づく、authority を区別するための一般的な方法を提供する。

authority 構成要素は、ダブルスラッシュ ("//") で始まり、次のスラッシュ ("/")、疑問符 ("?")、及び番号記号 ("#") のいずれかの文字、あるいは URI の終了によって終結する。

 authority   = [ userinfo "@" ] host [ ":" port ]

URI の生成を行うものや正規化を行うものは、port 要素が空の場合は、host と port とを分けるための ":" 区切り子を省略すべきである。 いくつかのスキームでは、userinfo や port 副構成要素を認めない。

URI が authority 要素を含む場合、path 要素は、空であるか、あるいはスラッシュ ("/") 文字で始めなければならない。 (単にその主構成要素から URI 参照を分離するような) 妥当性を確かめないパーサは、URI が逆参照される時まで、しばしば authority の副構成要素構造を無視し、ダブルスラッシュから最初の終端区切り子までを不明な{opaque} 文字列として扱うであろう。

3.2.1. ユーザ情報

userinfo 副構成要素は、ユーザ名と、任意でリソースにアクセスするための認証を得る方法についてのスキーム特有の情報を含むであろう。 ユーザ情報が存在する場合、ホストからそれを区切るための商業的アットサイン ("@") を従える。

 userinfo    = *( unreserved / pct-encoded / sub-delims / ":" )

userinfo において "user:password" 形式の使用は推奨されない。 アプリケーションは、コロンの後のデータが空文字列 (パスワードがない事を示す) でなければ、userinfo 副構成要素の中に見つけられる最初のコロン (":") 文字の後にいかなるデータも明文として表示すべきでない。 アプリケーションは、それを参照の一部として受け取る時、そのようなデータを無視するか、または拒絶するのを選ぶ事ができ、暗号化されていない形式においてはそのようなデータの保存を拒絶すべきである。 明文での認証情報の通過は、それが使用されているほとんどすべての場合においてセキュリティリスクがあるとわかっている。

グラフィカルなハイパーテキストのブラウジング等のような、ユーザフィードバックのために URI を表示するアプリケーションは、可能であれば、URI の残りの部分から区別される方法で userinfo を表示すべきである。 そのような表現は、 userinfo が誤解させるように扱われるドメイン名に似せて作られているような場合にユーザの助けとなるであろう (Section 7.6)。

3.2.2. ホスト

authority の host 副構成要素は、角括弧によって括られる IP 文字列、ドット付数字形式の IPv4 アドレス、及び登録名のいずれかによって識別される。 host 副構成要素は大文字・小文字を区別しない。 URI 内に host 副構成要素がある事が、スキームはインターネット上の与えられるホストへのアクセスを要求する事を意味するものではない。 多くの場合、host 構文は DNS のために作成され、展開される既存の登録手続きの再利用のためだけに使用され、その結果、別の登録を展開するコスト無しに全体において一意な名前を得る。 しかし、そのような使用はそれ自身のコストを伴う: ドメイン名所有権は時が経つと URI の生成を行うものによって予測されない理由によって変わるかもしれない。 そうでない場合、host 構成要素内のデータはインターネットホストとは関係ない登録名を特定する。 それがその唯一の目的ではなく、その最も一般的な目的であるので、我々は ABNF 規則のために "host" という名前を使用する。

 host        = IP-literal / IPv4address / reg-name

IPv4address と reg-name との間で完全に区別できないので、host のついての構文則はあいまいなものである。 この構文を区別するために、"first-match-wins" アルゴリズムを適用する: すなわち、host が IPv4address の規則に一致する場合は、それを IPv4 アドレス文字列とみなすべきだし、そうでなければ reg-name とみなすべきである。 host は大文字・小文字を区別しないが、URI の生成を行うものや正規化を行うものは、パーセントエンコーディングのためだけ大文字を使用し、画一性のために登録名や 16 進数字のアドレスについて小文字を使用すべきである。

インターネットプロトコルの文字列アドレス、バージョン 6 [RFC3513] 及びそれ以降によって識別される host は、角括弧 ("[" と "]") を伴う IP 文字列で括られる事によって区別される。 これは角括弧文字が URI 構文にて許される唯一の場所である。 将来のいまだ定義されていない IP 文字列アドレス形式での予想において、実装は発見的解決法{heuristic} の決定に従うよりも、そのような形式を明示的に示すために任意のバージョンフラグを使用するかもしれない。

 IP-literal = "[" ( IPv6address / IPvFuture  ) "]"

 IPvFuture  = "v" 1*HEXDIG "." 1*( unreserved / sub-delims / ":" )

バージョンフラグは IP バージョンを示さない; むしろ、将来の文字列形式のバージョンを示す。 その場合、実装は以下に記述される既存の IPv4 や IPv6 文字列アドレス形式においてバージョンフラグを提供してはならない。 "v" (大文字・小文字を区別しない) で始まる IP-literal を含む URI は、バージョンフラグが存在する事を示すが、そのバージョンフラグの意味を知らないアプリケーションによって逆参照されるが、アプリケーションは"アドレスメカニズムがサポートされていない" 事についての適切なエラーを返すべきである。

IPv6 文字列アドレスによって識別される host は、バージョンフラグが置かれる事なく角括弧内に表される。 ここで提供される ABNF は、[RFC3513] 内で提供される IPv6 文字列アドレスのテキスト定義の変形である。 この構文は、IPv6 scoped addressing zone identifiers をサポートしない。

128 ビットの IPv6 アドレスは、八つの 16 ビットの要素に分割される。 各要素は、一文字から四文字の 16 進数字を使用して (先行する 0 は認められる)、大文字・小文字を区別しない 16 進数字にて数値的に表現される。 八つのエンコードされた要素は、上位ビットが先に与えられ、コロン文字によって分割される。 任意で、下位の二つの要素は、代わりに IPv4 アドレスのテキスト形式にて表す事ができる。 アドレスに含まれる一つ以上の連続した 0 の 16 ビット要素の文字列は、それらの全ての数字を省略する事ができ、その省略を示すためにその場所にちょうど二つの連続したコロンを置く。

 IPv6address =                            6( h16 ":" ) ls32
             /                       "::" 5( h16 ":" ) ls32
             / [               h16 ] "::" 4( h16 ":" ) ls32
             / [ *1( h16 ":" ) h16 ] "::" 3( h16 ":" ) ls32
             / [ *2( h16 ":" ) h16 ] "::" 2( h16 ":" ) ls32
             / [ *3( h16 ":" ) h16 ] "::"    h16 ":"   ls32
             / [ *4( h16 ":" ) h16 ] "::"              ls32
             / [ *5( h16 ":" ) h16 ] "::"              h16
             / [ *6( h16 ":" ) h16 ] "::"

 ls32        = ( h16 ":" h16 ) / IPv4address
             ; アドレスの下位 32 ビット

 h16         = 1*4HEXDIG
             ; 16 進数字で表現される 16 ビットのアドレス

IPv4 文字列アドレスによって識別される host は、[RFC0952] を参照する [RFC1123] にて記述されるように、ドット付数字表記法 ("." によって分けられる、四つの 0 から 255 までの数字の連なり) によって表される。 Section 7.4 にて示されるように、いくつかのプラットフォームでは他のドット付数字表記法の形式が解釈されるかもしれないが、この文法では四つのオクテットのドット付数字表記法のみが許される事に注意せよ。

 IPv4address = dec-octet "." dec-octet "." dec-octet "." dec-octet

 dec-octet   = DIGIT                 ; 0-9
             / %x31-39 DIGIT         ; 10-99
             / "1" 2DIGIT            ; 100-199
             / "2" %x30-34 DIGIT     ; 200-249
             / "25" %x30-35          ; 250-255

登録名によって識別されるホストは、 URI のスキーム特有の意味論が特定の登録 (あるいは固定された名前テーブル) が代わりに使用される事を必要とするかもしれないが、通常ローカルで定義されるホストやサービス名登録の中のルックアップのための文字列である。 最も一般的な名前登録メカニズムは、ドメインネームシステム (DNS) である。 DNS 内のルックアップのための登録名は、 [RFC1034] の Section 3.5 と [RFC1123] の Section 2.1 にて定義される構文を使用する。 そのような名前は、"." によって分けられるドメインラベルの連なりから成り、各ドメインラベルの初めと最後はアルファベットか数字の文字であるが、その間では "-" を含む事もできる。 DNS における完全修飾ドメイン名{fully qualified domain name} の最も右のドメインラベルは単一の "." を付ける事ができ、完全なるドメイン名とあるローカルドメインとの間で区別する必要がある場合はそうすべきである。

 reg-name    = *( unreserved / pct-encoded / sub-delims )

URI スキームが host について初期値を定義する場合は、host 副構成要素が未定義である時、あるいは登録名が空 (長さ 0) である時に、その初期値が適用される。 例えば、"file" URI スキームでは、オーソリティがない、空のホスト、及び "localhost" が全てエンドユーザのマシンを意味するが、"http" スキームはオーソリティがない場合や空のホストは無効であるとみなす。

この仕様書では、特定の登録名ルックアップ技術を強制しないし、それ故に相互運用性に必要なもの以上に reg-name の構文を制限しない。 その代わり、登録名構文一致の問題を URI 解決を実行する各アプリケーションのオペレーティングシステムへと委託し、そのオペレーティングシステムはそれがホスト識別の目的のために何を認めるかを決定する。 URI解決実装は、登録名のルックアップのために、DNS、ホストテーブル、yellow page、NetInfo、WINS、あるいはその他のあらゆるシステムを使用する事ができる。 しかし、大局的範囲を持つ事が意図されている URI においては、DNS 完全修飾ドメイン名のような、大局的範囲の命名システムでは必要である。 URI の生成を行うものは、DNS の使用が直接的に明確でない時でさえ、DNS 構文に従う名前を使用すべきであり、それらの名前の長さを 255 文字未満に制限すべきである。

reg-name 構文は、基本的な名前解決技術に依存しないような単一の方法において非 ASCII 登録名を表すためにパーセントエンコードされるオクテットを認める。 UTF-8 [STD63] によれば、最初に非 ASCII 文字をエンコードし、その後に URI 文字として表すために UTF-8 文字列に対応する各オクテットをパーセントエンコードしなければならない。 URI 生成アプリケーションは、UTF-8 文字列を表すために使用するのでなければ、ホストにおいてパーセントエンコーディングを使用してはならない。 非 ASCII 登録名が DNS を通じての解決が意図された国際化ドメイン名を表す時、その名前は名前ルックアップの前に IDNA エンコーディング [RFC3490] へと変形されなければならない。 URI の生成を行うものは、古い URI リゾルバとの相互運用性を最大にしたいならば、それらの登録名をパーセントエンコーディングよりも、IDNA エンコーディングにて提供すべきである。

3.2.3. ポート

authority の port 副構成要素は、host の後に数値で任意のポート番号を示し、単一のコロン (":") 文字によって区切られる。

 port        = *DIGIT

スキームは、既定ポートを定義するかもしれない。 例えば、"http" スキームは、その対応する予約済 TCP ポート番号である、"80" の既定ポートを定義する。 ポート番号によって示されるポートのタイプ (例えば、TCP, UDP, SCTP) は、URI スキームによって定義される。 URI の生成を行うものや正規化を行うものは、ポートが空であるか、その値がスキームの初期値と同じである場合は、port 要素と ":" 区切り子を省略すべきである。

3.3. パス

path 構成要素は、通常は階層的形式にて組織されるデータと、非階層的な query 構成要素 (Section 3.4) 内のデータを伴い、その URI のスキームと (存在する場合は) 命名オーソリティの範囲内のリソースを識別するために利用される。 path は、最初の疑問符 ("?") か数字記号 ("#") の文字、あるいは URI の終わりによって終結する。

URI が authority 要素を含む場合、path 要素は空であるか、あるいはスラッシュ ("/") 文字をもって始まらなければならない。 URI が authority 要素を含まない場合、path はスラッシュ二文字 ("//") を持って始める事はできない。 更に、URI 参照 (Section 4.1) は relative-path 参照であるかもしれないが、その場合は最初の path の segment にはコロン (":") 文字を含む事はできない。 ABNF はこれらの場合を区別するために五つの異なる規則を必要とするが、与えられた URI 参照を含む path 部分文字列に一致するであろうものはその中の一つのみである。 我々は、パーサによってそれらの規則の一つに一致する URI 部分文字列を記述するために "path 構成要素" という一般用語を使用する。

 path          = path-abempty    ; "/" で始まるか、空
               / path-absolute   ; "/" で始まるが、"//" では始まらない
               / path-noscheme   ; コロンの無い segment で始まる
               / path-rootless   ; segment で始まる
               / path-empty      ; 文字が無い

 path-abempty  = *( "/" segment )
 path-absolute = "/" [ segment-nz *( "/" segment ) ]
 path-noscheme = segment-nz-nc *( "/" segment )
 path-rootless = segment-nz *( "/" segment )
 path-empty    = 0<pchar>

 segment       = *pchar
 segment-nz    = 1*pchar
 segment-nz-nc = 1*( unreserved / pct-encoded / sub-delims / "@" )
               ; non-zero-length segment without any colon ":"

 pchar         = unreserved / pct-encoded / sub-delims / ":" / "@"

path は、スラッシュ ("/") 文字によって分けられる path の segment の文字列から成る。 path は、空 (長さ 0) にて定義されるかもしれないが、URI について常に定義される。 URI が相対的参照のための状況として使用される時、階層を示すためのスラッシュ文字の使用のみが必要である。 例えば、URI <mailto: fred@example.com> は "fred@example.com" のパスを持つが、URI <foo://info.example.com?fred> は空のパスを持つ。

path の segment の "." と ".." は、ドットセグメント{dot-segments} としても知られるが、パス名階層の中で相対的参照のために定義される。 これらは、名前の階層木の中での相対的な位置を示すために relative-path 参照 (Section 4.2) の最初においての使用が意図される。 これは、それぞれ、カレントディレクトリと親ディレクトリを示すためのいくつかのオペレーティングシステムのファイルディレクトリ構造におけるそれらの役割と同様のものである。 しかし、ファイルシステムとは異なり、これらのドットセグメントは URI パス階層においてのみ解釈され、解決の過程の部分としては除かれる (Section 5.2)。

階層的なパスにおけるドットセグメントを除き、path の segment は一般的な構文では不明{opaque} であるとみなされる。 URI 生成アプリケーションは、しばしばスキーム特有、あるいは逆参照を扱うもの特有の副構成要素を区切るために segment において認められる予約済み文字を使用する。 例えば、セミコロン (";") やイコール ("=") の予約済み文字は、しばしばその segment に適切なパラメータとパラメータの値を区切るために使用されている。 コンマ (",") 予約済み文字も、しばしば同様の目的のために使用される。 例えば、ある URI を生成するものについて、"name" のバージョン 1.1 への参照を表すために "name;v=1.1" のようなセグメントを使用するかもしれないが、他のものでは同じものを表すために "name,1.1" のようなセグメントを使用するかもしれない。 パラメータの種類はスキーム特有の意味論によって定義されるであろうが、多くの場合、パラメータの構文は URI の逆参照アルゴリズムの実装に特定なものとなる。

3.4. クエリ

query 構成要素は、path 構成要素 (Section 3.3) のデータを伴い、その URI のスキームと (存在する場合は) 命名オーソリティの範囲内のリソースを識別するために利用される。 query 構成要素は、最初の疑問符 ("?") 文字によって始まり、数字記号 ("#") 文字、あるいは URI の終わりによって終結する。

 query       = *( pchar / "/" / "?" )

スラッシュ ("/") と疑問符 ("?") の文字は、query 要素の中のデータを表すかもしれない。 いくつかの古い、エラーのある実装では、それが相対的参照 (Section 5.1) の基底 URI として使用される場合、階層的な区切りを探す時に query データと path データの区別に失敗する事が多いので、そのようなデータを正しく扱わないかもしれない事に注意せよ。 しかし、query 構成要素はしばしば "key=value" の対の形式で識別するための情報を運ぶために使用され、そこで頻繁に使用された値は別の URI の参照なので、時にはそれらの文字をパーセントエンコーディングする事を避けるほうがユーザビリティのためにはよい。

3.5. フラグメント

URI の fragment 識別子構成要素は、主要リソースと追加識別情報の参照によって副次的リソースの二次的識別を認める。 識別される副次的リソースは、主要リソースの一部、あるいは部分集合か、主要リソースの表現上の見え方、あるいはそれらの表現によって定義されたり、表現されたりするその他のリソースであるだろう。 fragment 識別子構成要素は、数字記号 ("#") 文字の存在によって表され、URI の終わりによって終結する。

 fragment    = *( pchar / "/" / "?" )

fragment 識別子の意味論は、主要リソースへの取得動作から生じるであろう表現の集合によって定義される。 従って、fragment の形式と解決は、例えその URI が逆参照される場合にのみ、そのような取得が実行されるとしても、取得されうる表現のメディアタイプ [RFC2046] に依存する。 そのような表現が存在していなければ、fragment の意味論は未知であるとみなされ、事実上制限されない。 fragment 識別子の意味論は URI スキームに依存せず、それ故にスキームの仕様書によって再定義する事ができない。

それぞれのメディアタイプは、それら自身への制限や異なる部分集合の種類を識別するための fragment 識別子構文の中の構造、見え方、あるいはそのメディアタイプによる副次的リソースとして識別可能である外部参照を定義する事ができる。 主要リソースが複数の表現を持っている場合、そのリソースの表現が取得リクエストの属性に基づいて選択 (別名、内容ネゴシエーション) される場合にしばしばある事だが、fragment によって識別されるものは全てそれらの表現の全てに渡って一貫しているべきである。 各表現は、同じ副次的リソースに対応するための各々の fragment を定義するか、その存在にかかわらず fragment を未定義のままにしておく (すなわち、見つからない) かをすべきである。

任意の URI について、fragment 識別子要素の使用は取得動作が行われる事を意図するものではない。 fragment 識別子がある任意の URI について、主要リソースがアクセス可能、あるいは既にアクセスされているという事を意味する事無く、副次的リソースを示すために使用されるかもしれない。

fragment 識別子は、クライアント側の間接的参照の主要な形式として情報取得システムにおける特別な役割を持ち、これにより筆者はリソースの所有者によってのみ間接的に提供される既存のリソースの外観を明確に識別する事ができる。 その場合、fragment 識別子は URI のスキーム特有の処理には使用されない; その代わり、fragment 識別子は逆参照の前に残りの URI から分けられ、その結果、URI のスキームにかかわらず、fragment 自身内の識別するための情報はユーザエージェントによってのみ逆参照される。 この別々の取り扱いは、特にリソースは時が経つと移動するので参照の正確なリダイレクションについては、しばしば情報の損失であると考えられるが、これはまた、情報提供者が選択的に参照の作者にリソースの中の情報を参照するための権利を与えないためにも役立つ。 また、間接的な参照は、新たなメディアタイプの方が識別のための新たなスキームよりも定義も展開も容易なので、URI を使用するシステムに追加の柔軟性と拡張性を提供する。

スラッシュ ("/") と疑問符 ("?") 文字は、fragment 識別子内でデータを表す事ができる。 いくつかの古い、エラーのある実装では、それが相対的参照 (Section 5.1) の基底 URI として使用される場合、そのようなデータを正しく扱わないかもしれない事に注意せよ。

4. 使用法

アプリケーションが URI への参照を作成する時も、常に "URI" 構文則によって定義される参照の完全形を使用するわけではない。 記憶空間を節約するため、そして階層的局所性を利用するために、多くのインターネットプロトコル要素やメディアタイプでは、URI の省略を認めており、また他のものではその構文を特定の形式の URI に制限する。 我々は、一般的な構文の設計に影響を与え、かつ依存する事になるので、整合性をもって解釈されるために統一した解析アルゴリズムを必要とする、この仕様書における最も一般的な参照構文の形式を定義する。

4.1. URI 参照

URI-reference は、リソース識別の最も一般的な使用法を示すために使用される。 identifier.

 URI-reference = URI / relative-ref

URI-reference は、URI か相対的参照のどちらかである。 URI-reference の先頭がコロン分離記号を従えるスキームの構文に合致しなければ、URI-reference は相対的参照である。

URI-reference は通常、どんな構成要素が存在するか、そしてその参照が相対的であるかどうかを決定するために、初めに五つの URI 構成要素にて解析される。 そして、各構成要素は、その副要素とそれの妥当性について解析される。 "first-match-wins" による曖昧さの解消規則を利用した、URI-reference の ABNF は、一般的な構文について妥当性を検証するためのパーサを定義するためには十分である。 正規表現に精通している読者は、あらゆる与えられた文字列を取り、URI 構成要素を抽出するための、妥当性は検証されない URI-reference パーサの例について付録 B を見るべきである。

4.2. 相対的参照

相対的参照は、別の階層的な URI の名前空間に関連する URI 参照を表現するために階層的な構文 (Section 1.2.3) を利用する。

 relative-ref  = relative-part [ "?" query ] [ "#" fragment ]

 relative-part = "//" authority path-abempty
               / path-absolute
               / path-noscheme
               / path-empty

相対的参照によって参照される URI は、目標 URI としても知られるが、Section 5 の参照解決アルゴリズムを適用する事によって得られる。

二つのスラッシュ文字をもって始まる相対的参照は、ネットワークパス参照と呼ばれる; しかし、このような参照はめったに使用されない。 単一のスラッシュ文字をもって始まる相対的参照は、絶対パス参照と呼ばれる。 スラッシュ文字をもっては始まらない相対的参照は、相対パス参照と呼ばれる。

コロン文字を含む path のセグメント (例えば、"this:that") は、それがスキーム名と間違えられるだろうから、相対パス参照の最初のセグメントとしては使用できない。 そのようなセグメントは、相対パス参照を作るためには、ドットセグメントによって先行されなければならない (例えば、"./this:that")。

4.3. 絶対 URI

いくつかのプロトコル要素では、fragment 識別子のない URI の絶対形式のみを認めている。 例えば、相対的参照によって後の使用のために基底 URI を定義する事は、fragment を認めない absolute-URI 構文規則を要求する。

 absolute-URI  = scheme ":" hier-part [ "?" query ]

URI スキーム仕様書では、それらのスキーム特有の構文に合致する全ての文字列が <absolute-URI> の文法にも合致するようにそれら自身の構文を定義しなければならない。 スキームの仕様書では、fragment の識別がスキームの定義と直交しているので、そのスキームを通じての識別可能なリソースへの適用性にかかわらず、fragment 識別子の構文や使用法を定義しないであろう。 しかし、スキームの仕様書は、広範囲な例、例えばそのような使用法が適切である時の fragment 識別子をもつスキームの URI の使用に示す例を、含んでいる事が推奨される。

4.4. 同一文書の参照

URI 参照が、(存在する場合) その fragment 構成要素を除き、基底 URI (Section 5.1) と同一の URI を参照する時、その参照は "同一文書" 参照と呼ばれる。 同一文書参照の最もよくある例は、空であるか、数字記号 ("#") 分離記号の後に fragment 識別子のみを含むような相対的参照である。

同一文書参照が取得動作のために逆参照される時、その参照の目標は参照と同じエンティティ (表現、文書、あるいはメッセージ) の中にあるとして定義される; 従って、逆参照は新たな取得動作を起こすべきではない。

Section 6.2.26.2.3 にて記述されるように、基底 URI と目標 URI の比較の前の正規化は、認められているが、実際にはめったに実行されない。 正規化は同一文書参照の集合を増やすかもしれないが、それはいくつかのキャッシュアプリケーションにとって利益となるかもしれない。 その場合、参照の作者は、等価だけれども、わずかに異なる参照 URI があらゆる与えられたアプリケーションによって同一文書参照として解釈されるだろう (あるいはされないだろう) という事を仮定すべきではない。

4.5. 接尾辞参照

URI 構文は、曖昧でないリソースへの参照と URI スキームを通じての確証性のために設計される。 しかし、URI の識別と使用は一般的になり、伝統的なメディア (テレビ、ラジオ、新聞、掲示板等) は次第に参照として URI の後半部分、すなわち URI の authoriry や path の部分のみから成るものを使用してきている。例えば、

 www.w3.org/Addressing/

あるいは、単に所有する DNS 登録名を使用するものもある。 このような参照は、主にマシンのためというよりむしろ人間の解釈のためとして意図されており、その URI を完成するためには文脈に基づく発見的教授法{heuristics} で十分 (例えば、"www" で始まるほとんどの登録名は URI の先頭部分に "http://" というものを持っていそうである) という仮定をもっている。 URI の後半部分を区別するための標準の発見的教授法の集合はないが、多くのクライアント実装によって、それらはユーザによって入力され、発見的に解決される事ができる。

この後半部分の参照を使用する習慣は一般的ではあるが、これは可能であればいつでも避けるべきで、長い間参照する事が予想される状況では決して使用されるべきではない。 上述の発見的教授法は、時が経てば、特に新たな URI スキームが流行すれば変化するし、きちんとした理由付けなく使用されると、しばしば不正確である。 その上、これらは [RFC1535] にて記述されるものに従ってセキュリティの問題に通じるであろう。

URI の後半部分が相対パス参照と同じ構文を持つ時、後半部分による参照は相対的参照が予想される文脈においては使用できない。 結果として、 後半部分による参照は、ダイアログボックスやオフライン広告のような、定義される基底 URI がない場所に制限される。

5. 参照の解決

この節では、相対的参照を認める文脈の中で URI 参照を解決する手順を定義するので、その結果は Section 3 の <URI> 構文則に合致する文字列である。

5.1. 基底 URI の確立

"相対{relative}" という用語は、相対的参照が適用されている "基底 URI" が存在するという事を意味するものである。 fragment のみの参照 (Section 4.4) を除き、基底 URI が既知である時のみ相対的参照が利用できる。 基底 URI は、パーサによって相対的であるかもしれない URI 参照を解析する前に確立されなければならない。 基底 URI は、<absolute-URI> 構文則 4.3) に従わなければならない。 基底 URI が URI 参照から得られる場合、その参照は絶対形式に変換され、基底 URI として使用する前にあらゆる fragment 構成要素を取り除かなければならない。

参照の基底 URI は、優先順に以下で議論され、その四つの方法のうちの一つをもって確立する事ができる。 優先順は層の表現で考えられ、最も内部で定義される基底 URI が最も高い優先度を持っている。 これは、以下のように図式化して視覚化する事ができる:

         .----------------------------------------------------------.
         |  .----------------------------------------------------.  |
         |  |  .----------------------------------------------.  |  |
         |  |  |  .----------------------------------------.  |  |  |
         |  |  |  |  .----------------------------------.  |  |  |  |
         |  |  |  |  |       <relative-reference>       |  |  |  |  |
         |  |  |  |  `----------------------------------'  |  |  |  |
         |  |  |  | (5.1.1) 本文内に埋め込まれた基底 URI   |  |  |  |
         |  |  |  `----------------------------------------'  |  |  |
         |  |  | (5.1.2) カプセル化しているエンティティからの |  |  |
         |  |  |         基底 URI (メッセージ, 表現, なし)    |  |  |
         |  |  `----------------------------------------------'  |  |
         |  | (5.1.3) 取得される URI からの基底 URI              |  |
         |  `----------------------------------------------------'  |
         | (5.1.4) 基底 URI の初期値 (アプリケーション依存)         |
         `----------------------------------------------------------'

5.1.1. 本文内に埋め込まれた基底 URI

特定のメディアタイプの中では、パーサが相対的参照のための基底 URI をすぐに得る事ができるように、内容そのものの中にそれを埋め込む事ができる。 これは、目次のような、説明的文書のために役立つであろうし、それらの通常の取得の状況 (例えば、電子メールや USENET ニュース) 以外のプロトコルを通じて他のものへと転送する事ができる。

各メディアタイプが、どのように基底 URI を埋め込めるかを規定する事は、この仕様の範囲を超えている。 それらが利用可能であれば、適切な構文は各メディアタイプに関連するデータ形式の仕様書によって記述される。

5.1.2. カプセル化しているエンティティからの基底 URI

基底 URI が埋め込まれていない場合、基底 URI はその表現の取得の状況によって定義される。 メッセージかアーカイブのような、別のエンティティ内に同封される文書については、取得の状況とはそのエンティティである。 従って、表現の初期基底 URI は、その表現がカプセル化されているエンティティの基底 URI である。

MIME 内包タイプ内 (例えば、メッセージとマルチパートタイプ) の基底 URI を埋め込むためのメカニズムは、MHTML [RFC2557] によって定義される。 MIME メッセージヘッダ構文は使わないが、いくつかのタグ付けされる外部データの形式をメッセージ内に含む事を認めるようなプロトコルでは、メッセージの一部として基底 URI を定義するためのそれら自身の構文を定義する事ができる。

5.1.3. 取得される URI からの基底 URI

基底 URI が埋め込まれておらず、またその表現が他のエンティティにカプセル化されていない場合に、 表現の取得に URI が使われたならば、その URI を基底 URI とみなすものとする。 もしその取得がリダイレクトされたリクエストの結果の場合、最後に使用された URI (すなわち、実際の表現取得をもたらした URI) が基底 URI である。

5.1.4. 基底 URI の初期値

上述の条件がいずれも適用されない場合、基底 URI はアプリケーションの状況によって定義される。 この定義は必然的にアプリケーション依存であり、他の方法のいずれかを使用した基底 URI の定義に失敗した場合、同じ内容が違う種類のアプリケーションによっては異なる解釈がなされるかもしれない。

相対的参照を含む表現の送信者は、それらの参照の基底 URI が確立できる事を保証する責任がある。 fragment のみの参照を除き、相対的参照は基底 URI がちゃんと定義された状況でのみ信頼して使用する事ができる。

5.2. 相対性の解決

この節では、参照の目標の解析された構成要素の中で与えられた基底 URI に相対かもしれない URI 参照を変換するためのアルゴリズムを記述する。 構成要素は、Section 5.3 にて記述されるように、目標 URI を形成するために、再構成されるだろう。 このアルゴリズムは、他の実装の出力をテストするために使用する事ができる最終的な結果を提供する。 アプリケーションは、その結果がこの方法によって与えられるものと合致するならば、いくつかの他のアルゴリズムを使用する事によって相対的参照の解決を実装する事ができる。

5.2.1. 基底 URI を解析する前に

基底 URI (Base) は、Section 5.1 の手順によって確立され、Section 3 にて記述された 5 つの主な構成要素に構文分析される。 基底 URI においては、scheme 要素のみ必須である事に注意せよ; 他の要素は、空であるか、あるいは未定義であるかもしれない。 それに関連する区切り子が URI 参照内に現れなければ、構成要素は未定義である; path 要素は空であるかもしれないが、決して未定義ではない。

Section 6.2.26.2.3 にて記述されるような、基底 URI の正規化は、任意である。 URI 参照は、正規化される前に目標 URI へと変形されなければならない。

5.2.2. 参照の変形

各 URI 参照 (R) について、以下の擬似コードは R を目標URI (T) に変換するためのアルゴリズムを説明するものである:

 -- URI 参照は 5 つの URI 構成要素に構文分析される。
 --
 (R.scheme, R.authority, R.path, R.query, R.fragment) = parse(R);

 -- 厳格でないパーサは、それが基底 URI のスキームと同一であれば、
 -- 参照内のスキームを無視するかもしれない。
 --
 if ((not strict) and (R.scheme == Base.scheme)) then
    undefine(R.scheme);
 endif;

 if defined(R.scheme) then
    T.scheme    = R.scheme;
    T.authority = R.authority;
    T.path      = remove_dot_segments(R.path);
    T.query     = R.query;
 else
    if defined(R.authority) then
       T.authority = R.authority;
       T.path      = remove_dot_segments(R.path);
       T.query     = R.query;
    else
       if (R.path == "") then
          T.path = Base.path;
          if defined(R.query) then
             T.query = R.query;
          else
             T.query = Base.query;
          endif;
       else
          if (R.path starts-with "/") then
             T.path = remove_dot_segments(R.path);
          else
             T.path = merge(Base.path, R.path);
             T.path = remove_dot_segments(T.path);
          endif;
          T.query = R.query;
       endif;
       T.authority = Base.authority;
    endif;
    T.scheme = Base.scheme;
 endif;

 T.fragment = R.fragment;

5.2.3. パスの併合

上記の擬似コードは、relative-path 参照と基底 URI のパスとを併合するための "併合" の手順を示す。 これは、以下のようにして達成される。

5.2.4. ドットセグメントの削除

また、擬似コードは、参照された path から特別な "." または ".." の完全 path セグメントを解釈し、削除ための "remove_dot_segments" の手順も示す。 これは、そのパスが相対的であったどうかにかかわらず、目標 URI を形成する前にいかなる無効な、あるいは余分なドットセグメントも取り除くために、参照から path を抽出した後に行われる。 この削除を達成するには多くの方法があるが、我々は二つの文字列バッファを使用する単純な方法を記述する。

  1. 入力バッファは現在追加されているパス部品で初期化され、出力バッファは空の文字列にて初期化される。
  2. 入力バッファが空でない間、以下をループする:
    1. 入力バッファの先頭部分が "../" や "./" で始まるならば、入力バッファからその部分を取り除く; もしくは、
    2. 入力バッファの先頭部分が "/./" や "/." で始まるならば、"." が完全パスセグメントの場合、入力バッファ内のその部分を "/" に置き換える; もしくは、
    3. 入力バッファの先頭部分が "/../" や "/.." で始まるならば、".." が完全パスセグメントの場合、入力バッファ内のその部分を "/" に置き換え、出力バッファから最後のセグメントと (ある場合) それに先行する "/" を削除する; もしくは、
    4. 入力バッファが "." や ".." のみから成るならば、入力バッファからそれを削除する; もしくは、
    5. 入力バッファの最初のセグメント、すなわち (ある場合) 最初の "/" 文字から、次の "/" を含まないそこまでの全ての文字、あるいは入力バッファの最後を、出力バッファの最後へと移動する。
  3. 最後に、出力バッファが remove_dot_segments の結果として返される。

ドットセグメントは、URI 参照において基底 URI 内の名前の階層に相対的な識別子を表すための使用を意図するものである事に注意せよ。 remove_dot_segments アルゴリズムは、それを逆参照する実装によってエラーとしたり誤って解釈されたまま扱うより、余分なドットセグメントを削除する事によって、その階層を尊重する。

以下では、各ステップ後の二つのバッファの状態を示す事によって、併合されるパスの二つの例について上記のステップがどのように適用されるかを例示する。

 STEP   OUTPUT BUFFER         INPUT BUFFER

  1 :                         /a/b/c/./../../g
  2E:   /a                    /b/c/./../../g
  2E:   /a/b                  /c/./../../g
  2E:   /a/b/c                /./../../g
  2B:   /a/b/c                /../../g
  2C:   /a/b                  /../g
  2C:   /a                    /g
  2E:   /a/g

 STEP   OUTPUT BUFFER         INPUT BUFFER

  1 :                         mid/content=5/../6
  2E:   mid                   /content=5/../6
  2E:   mid/content=5         /../6
  2C:   mid                   /6
  2E:   mid/6

いくつかのアプリケーションでは、文字列よりも二つのセグメントスタックを使った remove_dot_segments アルゴリズムの実装の方がより効果的であるとわかるかもしれない。

注: いくつかの古い、エラーを持つ実装は、基底 URI と参照パスを併合する前に参照の path 要素から query 要素を分ける事に失敗し、その query 要素に "/../" や "/./" の文字列を含む場合には相互動作上の失敗を引き起こすという事に注意せよ。

5.3. 構成要素の再構成

解析された URI 構成要素は、対応する URI 参照文字列を得るために再構成される。 これは、擬似コードを使用すると、以下のようになる:

 result = ""

 if defined(scheme) then
    append scheme to result;
    append ":" to result;
 endif;

 if defined(authority) then
    append "//" to result;
    append authority to result;
 endif;

 append path to result;

 if defined(query) then
    append "?" to result;
    append query to result;
 endif;

 if defined(fragment) then
    append "#" to result;
    append fragment to result;
 endif;

 return result;

我々は、参照内に分離記号がなかった事を意味する、定義されていない構成要素と、分離記号があるがそのすぐ後に次の構成要素の分離記号か参照の終わりがあった事を意味する、空の構成要素の間の区別を慎重に保存する事に注意せよ。

5.4. 参照の解決の例

以下の十分に定義された基底 URI

 http://a/b/c/d;p?q

を持つ表現において、相対的参照はその目標 URI を以下のように変形する。

5.4.1. 通常の例

 "g:h"           =  "g:h"
 "g"             =  "http://a/b/c/g"
 "./g"           =  "http://a/b/c/g"
 "g/"            =  "http://a/b/c/g/"
 "/g"            =  "http://a/g"
 "//g"           =  "http://g"
 "?y"            =  "http://a/b/c/d;p?y"
 "g?y"           =  "http://a/b/c/g?y"
 "#s"            =  "http://a/b/c/d;p?q#s"
 "g#s"           =  "http://a/b/c/g#s"
 "g?y#s"         =  "http://a/b/c/g?y#s"
 ";x"            =  "http://a/b/c/;x"
 "g;x"           =  "http://a/b/c/g;x"
 "g;x?y#s"       =  "http://a/b/c/g;x?y#s"
 ""              =  "http://a/b/c/d;p?q"
 "."             =  "http://a/b/c/"
 "./"            =  "http://a/b/c/"
 ".."            =  "http://a/b/"
 "../"           =  "http://a/b/"
 "../g"          =  "http://a/b/g"
 "../.."         =  "http://a/"
 "../../"        =  "http://a/"
 "../../g"       =  "http://a/g"

5.4.2. 特異な例

以下の異常な例は実際には起こないであろうが、 全ての URI パーサは一貫性を持ってそれらを解決できるようにすべきである。 各例は上と同じ基底を使用する。

パーサは、relative-path 参照内に基底 URI の path 内の階層以上の ".." 以上のセグメントがある場合、その取り扱いに慎重でなければならない。 ".." 構文は、URI の authority 構成要素を変えるためには使用できないという事に注意せよ。

 "../../../g"    =  "http://a/g"
 "../../../../g" =  "http://a/g"

同様に、"." や ".." のドットセグメントが path の完全な構成要素である時は、パーサはそれらを取り除かなければならないが、それらがセグメントの一部であるだけの時は、それらを取り除いてはならない。

 "/./g"          =  "http://a/g"
 "/../g"         =  "http://a/g"
 "g."            =  "http://a/b/c/g."
 ".g"            =  "http://a/b/c/.g"
 "g.."           =  "http://a/b/c/g.."
 "..g"           =  "http://a/b/c/..g"

相対的参照が "." や ".." 完全パスセグメントの不要な、あるいは無意味な形式を使用する場合はほとんどない。

 "./../g"        =  "http://a/b/g"
 "./g/."         =  "http://a/b/c/g/"
 "g/./h"         =  "http://a/b/c/g/h"
 "g/../h"        =  "http://a/b/c/h"
 "g;x=1/./y"     =  "http://a/b/c/g;x=1/y"
 "g;x=1/../y"    =  "http://a/b/c/y"

いくつかのアプリケーションでは、query 経路や fragment 要素を、基底 path に併合し、ドットセグメントを削除する前に、参照の path 要素から切り離して失敗する。 通常の fragment の使用では決して階層 ("/") 文字を含まないし、query 要素は通常相対的参照の中では使用されないので、この誤りはほとんど気づかれない。

 "g?y/./x"       =  "http://a/b/c/g?y/./x"
 "g?y/../x"      =  "http://a/b/c/g?y/../x"
 "g#s/./x"       =  "http://a/b/c/g#s/./x"
 "g#s/../x"      =  "http://a/b/c/g#s/../x"

いくつかのパーサでは、基底 URI のスキームと同じ場合、相対的参照内にスキームが存在する事を認める。 これは、以前の部分的 URI [RFC1630] の仕様書における抜け穴であるとみなされる。 その使用は避けられるべきであるが、後方互換性のために許されている。

 "http:g"        =  "http:g"         ; 厳格なパーサでは
                 /  "http://a/b/c/g" ; 後方互換性のために

6. 正規化と比較

URI へので最も一般的な操作の一つは、単純な比較である: すなわち、二つの URI が等価であるかどうかをそれぞれのリソースにアクセスするために URI を使用せずに決定する。 比較は、レスポンスキャッシュがアクセスされている時、ブラウザがリンクを着色するために履歴をチェックする時、あるいは XML パーサが名前空間の中でタグを処理する時は常に実行されている。 URI の比較の前の広範囲な正規化は、検索空間を切り詰めるため、あるいはリクエスト動作とレスポンス格納のコピーを減らすためにしばしばスパイダや索引付けエンジンによって使用される。

URI 比較は、ある特定の目的のために実行される。 異なる目的のために URI を比較するプロトコルや実装は、エイリアス識別子を減らすためにどのくらいの努力が費やされるべきであるかに関して、しばしば異なる設計上の妥協{trade-offs} を強いる。 この節では、URI を比較するために使用されるであろう様々な方法、それらの間の妥協点、及びそれらを使用するかもしれないアプリケーションの種類について記述する。

6.1. 等価

URI はリソースを識別するために存在しているので、それらが同じリソースを識別する時は、それらは等価であるだろうと考えられるべきである。 しかし、この等価性の定義は、実装がそれらについての完全な知識、あるいは制御を持つのでなければ、二つのリソースを比較する方法が全くない時には、あまり実用のものではない。 この理由のために、URI の等価や相違の決定は、おそらく URI スキームの定義によって提供される付則の参照で補正される文字列比較に基づいている。 我々は "相違{different}" と "等価{equivalent}" という用語をそのような比較の可能な結果を記述するために使用するが、等価性には多くのアプリケーション依存な種類がある。

二つの URI が等価である事を決定する事は可能であるが、URI 比較は二つの URI が異なるリソースを識別するかどうか決定するためには十分ではない。 例えば、二つの異なるドメイン名の所有者は、二つの URI は異なるけれども、両方から同じリソースを供給する事を決定する事ができる。 従って、比較方法は、偽陽性{false positives} を厳密に避ける一方で、偽陰性{false negatives} を最小にするように設計される。

等価性についてテストする際、アプリケーションは相対的参照を直接比較すべきではない; すなわち、それらの参照は比較の前にそれぞれの目標 URI に変換されるべきである。 URI が、表現の取得のような、ネットワーク動作を選択する (あるいは避ける) ために比較される時、fragment 要素は (存在する場合) その比較から除かれるべきである。

6.2. 比較の梯子

URI の等価性をテストするために、実際には様々な方法が使用される。 これらの方法は、必要な処理の量や偽陰性の確立が減らされる度合いによって区別され、分類される。 上述の通り、偽陰性は取り除く事はできない。 実際には、それらの確率を減らす事はできるが、減らすために更なる処理が必要であり、全てのアプリケーションにおいて費用対効果に優れているわけではない。

この比較実行範囲を梯子であるとみなせば、以下の議論では、簡単であるが相対的に偽陰性を生み出す可能性が高いものから始まり、より高いコンピュータ上のコストとより低い偽陰性のリスクを持つ手順へと続く、梯子を昇るであろう。

6.2.1. 単純な文字列の比較

二つの URI が、文字列であるとみなされる時に、同一であるなら、それらが等価であると結論づける事は安全である。 この種の等価性テストは、コンピュータ上のコストが非常に低く、様々なアプリケーションにて、特にドメインの構文解析において、広く使用されている。

等価性について文字列をテストするためには、いくつかの基本的な事前の注意が必要である。 この手順は、しばしば "ビット毎{bit-for-bit}" あるいは "バイト毎{byte-for-byte}" 比較と呼ばれるが、これらは潜在的に紛らわしい。 通常、文字列の等価性についてのテストは、文字列を作る文字の組比較に基づき、先頭から始めて、両方の文字列が終わるまで全ての文字が等しいとわかるまで、一組の文字が等しくない、あるいは文字列の一方がもう片方より前に取り尽くされる{exhausted} まで、続ける。

この文字の比較には、各組の文字が比較され得る形式に収められる必要がある。 例えば、ある URI が EBCDIC エンコーディングによってバイト配列に格納されており、もう一つが Java String オブジェクト (UTF-16) にて格納されているとすれば、単純に適用されるビット毎の比較はエラーを引き起こすであろう。 バイト毎あるいはビット毎に基づくよりも、文字毎に基づいて等価性を語る方が良い。 実際的な言い方をするなら、文字毎の比較は共通の文字エンコーディングへと変換した後にコードポイント毎に行われるべきである。

偽陰性は、URI エイリアスの生成と使用によって引き起こされる。 不必要なエイリアスは、比較方法にかかわらず、一貫して URI 参照を既に正規化された形 (すなわち、以下に記述されるように、正常化が適用された後に生産されるものと同じ形) で提供することによって、減らす事ができる。

プロトコルやデータ形式は、しばしば いくつかの URI 比較を単純な文字列比較に制限する。 人々や実装はそれぞれの最大の利益のために、一貫した URI 参照を提供する、あるいは少なくても更なる正規化から得られる効果を打ち消す程度には一貫した URI 参照を提供するであろうとの論理に基づいて、プロトコルやデータ書式はしばしばいくつかの URI の比較を単純な文字列の比較に限定している。

6.2.2. 構文に基づく正規化

実装は、偽陰性の確率を減らすためにこの仕様書によって提供される定義に基づく論理を使用する事ができる。 この処理は、文字毎の文字列比較よりもどちらかというとコストが高い。 例えば、このやり方を使用するアプリケーションは、以下の二つの URI が等価であると合理的にみなし得る:

 example://a/b/c/%7Bfoo%7D
 eXAMPLE://a/./b/../b/%63/%7bfoo%7d

ブラウザ等の Web ユーザエージェントは、 キャッシュされるレスポンスが利用可能であるかどうか決定する時、通常この種の URI 正規化を適用する。 構文に基づく正規化は、大文字・小文字の正規化、パーセントエンコーディングの正規化、及びドットセグメントの削除等の技術を含む。

6.2.2.1. 大文字・小文字の正規化

全ての URI について、パーセントエンコーディング三重語中の 16 進数字 (例えば、"%3a" に対する "%3A") は大文字・小文字を問わず、従って数字 A-F にあたる文字は大文字を使用するように正規化されるべきである。

URI が一般的構文の構成要素を使用する時、構成要素の構文等価性の規則は常に適用される; すなわち、scheme や host は大文字・小文字を問わないので、小文字で正規化されるべきである。 例えば、URI "HTTP://www.EXAMPLE.com/" は "http://www.example.com/" と等価である。 他の一般的な構文の構成要素は、スキームによってそうでないと明確に定義されていなければ、大文字・小文字を区別すると仮定する (Section 6.2.3 参照)。

6.2.2.2. パーセントエンコーディングの正規化

パーセントエンコーディングメカニズム (Section 2.1) は、本来同一の URI における相違の大きな原因である。 上記の大文字・小文字の正規化の問題に加え、URI を生成するものの中には、パーセントエンコーディングする必要のないオクテットをパーセントエンコードするものもあり、その結果それらはエンコードされていなければ等価である URI となる。 これらの URI は、Section 2.3 にて記述されるように、あらゆるパーセントエンコードされたオクテットを対応する非予約文字へとデコードする事によって正規化されるべきである。

6.2.2.3. パスセグメントの正規化

完全パスセグメント "." と ".." は相対的参照 (Section 4.1) 内での使用のみが意図されており、参照の解決処理 (Section 5.2) の一部として削除される。 しかし、展開される実装の中には、参照が既に URI である時は参照解決が必要でないと誤った仮定をし、その結果相対的パスでない時にはドットセグメントを削除しないものもある。 URI を正規化するものは、Section 5.2.4 に記述されるように、path に remove_dot_segments アルゴリズムを適用する事によってドットセグメントを削除すべきである。

6.2.3. スキームに基づく正規化

URI の構文や意味論は、各スキームのための定義仕様書によって説明されるように、スキーム毎に異なるであろう。 実装は、偽陰性の確率を減らすために、更なる処理コストを費やす事で、スキーム特有の規則を使用する事ができる。 例えば、"http" スキームは、既定ポート "80" を持つ authority 構成要素を利用し、空の path は "/" は等価であると定義するので、以下の四つの URI は等価である:

 http://example.com
 http://example.com/
 http://example.com:/
 http://example.com:80/

一般に、空の path を持つ authority への一般的な構文を使用する URI は、path を"/" と正規化すべきである。 同様に、port が空であるか、そのスキームにとって初期値であるような、明示された ":port" は、port とその ":" 区切り子が削除されたものと等価であり、従ってスキームに基づく正規化によって取り除かれるべきである。 例えば、上の二番目の URI は "http" スキームについての標準形である。

正規化がスキームによって異なるもう一つの場合に、空の authority 構成要素あるいは空の host 副構成要素の取り扱いにおけるものがある。 多くのスキームの仕様書において、空の authority や host は誤りであるとみなされる; それ以外のものにおいては、"localhost" あるいはエンドユーザのホストと等価であるとみなされる。 スキームが authority についての初期値を定義しており、その初期値への URI 参照を望む時、その参照は、統一性、簡潔性、及び国際化のために空の authority に正規化されるべきである。 しかし、userinfo か port のどちらかの副構成要素が空でない場合、それが初期値に合致しても、host が明示的に与えられるべきである。

ある構成要素が空である時に、スキームの仕様書によってそうする事が認められなければ、正規化では区切り子を取り除くべきではない。 例えば、URI "http://example.com/?" は上記の例のいずれかに等価であると仮定する事はできない。 同様に、userinfo 副構成要素中の区切り子の有無は通常その解釈に重要である。 fragment 構成要素は、どんなスキームに基づく正規化にも従属しない; 従って、接尾語 "#" のみ異なる二つの URI は、そのスキームにかかわらず異なるとみなされる。

いくつかのスキームでは、大文字・小文字を区別しないデータから成る追加的副構成要素を定義し、 正規化を行うものへこのデータをよくある例 (例えば、全て小文字) に変換するために暗黙の許可を与える。 例えば、"mailto" URI スキームのような、インターネットホスト名を含むための path の副構成要素を定義する URI スキームは、 その副構成要素が大文字・小文字を区別しない事になり、それ故に大文字・小文字の正規化を受ける事になる (例えば、一般的な構文では path 構成要素は大文字・小文字を区別するとみなすが、"mailto:Joe@Example.COM" は "mailto:Joe@example.com" と等価である)。

この他のスキーム特有な正規化も可能である。

6.2.4. プロトコルに基づく正規化

偽陰性の発生を減少させるための相当な努力は、しばしば Web スパイダにとって費用対効果に優れている。 従って、それらは URI 比較において、より積極的な技術を実装する。 例えば、それらが以下のような URI

 http://example.com/data

を見たとすると、最後のスラッシュのみ異なる URI へとリダイレクトする

 http://example.com/data/

それらは、将来において、おそらく二つが等価であるとみなすであろう。 この種の技術は、リソースにアクセスした結果とそれらのスキームの逆参照アルゴリズムの一般的慣習 (この場合、相対的参照における問題を避けるための HTTP オリジンサーバによるリダイレクションの使用) の両方によって等価性が明確に示される時にのみ適切である。

7. セキュリティについての考察

URI は、本来セキュリティ上の脅威とならない。 しかし、URI はしばしばネットワークリソースへのアクセスのための指標の緊密した{compact} 集合を提供するために使用されるので、 URI 内のデータを適切に解釈する事、そのデータが意図されないアクセスを引き起こすのを防ぐ事、そして平文で表されるべきではないデータを含む事を避ける事に、注意をしなければならない。

7.1. 信頼性と整合性

URI が情報を取得するために一度使用されたからといって、将来において同じ情報がその URI によって取得可能であるだろうという保証はない。 また、将来においてその URI を通じて取得可能な情報が過去に取得されたそれと著しく同様であるだろうという保証も全くない。 URI 構文は、与えられるスキームやオーソリティがどのようにその名前空間を割り当てるか、あるいは時を経た後にどうそれを維持するかを束縛しない。 そのような保証は、名前空間や問題となっているリソースを制御している人 (達) からのみ得る事ができる。 特定の意味論がある特定の URI スキームのための全ての命名機関{naming authorities} に必要な場合、その URI スキームは、名前永続性のような、追加的意味論を定義する事ができる。

7.2. 悪意のある構造

表現の取得のような、一見無害で、冪等{idempotent} な操作を実行しようとすると、実際には損害を与える遠隔操作の原因となり得るような URI を構築する事が可能である。 安全でない URI は、通常問題となっているネットワークプロトコルのために予約されているもの以外のポート番号を指定する事によって構築される。 クライアントは、無意識の内に異なるプロトコルサービスを走らせているサイトへと接触し、その URI 中のデータにはこの他のプロトコルによって解釈される時、意図せぬ動作を引き起こすような指示が含まれている。 そのような悪用のよく見られる例として、"25" という port 構成要素をもつプロトコルに基づいたスキームの使用があり、その結果 SMTP サーバを通じて意図されない、あるいはなりすましのメッセージを送るようにユーザエージェントソフトウェアをだます。

アプリケーションは、その URI の逆参照に使用されているプロトコルが "well-known port" 上で予測されるプロトコルと互換性があるのでなければ、well-known port の範囲 (0-1023) 中の TCP ポート番号を指定する URI の逆参照を防ぐべきである。 IANA は well-known port の登録は継続しているけれども、アプリケーションは新たなサービスの展開が妨げられないようにそのような制限をユーザが設定可能とすべきである。

URI が与えられる解決や反参照プロトコルのための区切り子に合致するパーセントエンコードされたオクテット (例えば、TELNET プロトコルにおける CR と LF の文字) を含む時、それらのパーセントエンコーディングはプロトコルを通じた転送の前にデコードされてはならない。 プロトコルに違反するかもしれないパーセントエンコーディングの転送は、デコードされたオクテットが追加的操作あるいは引数として解釈され、予期されないかつ有害であろう遠隔操作を引き起こしてしまうかもしれない事を認めるよりは害が少ない。

7.3. 後置のコード変換{Back-End Transcoding}

URI が逆参照される時、その中のデータはしばしばユーザエージェントと一つ以上のサーバの両方によって解析される。 例えば、HTTP において、典型的なユーザエージェントは、URI を五つの主な構成要素要へと分析し、authority のサーバへアクセスし、authority, path, query 各構成要素中のデータを送るであろう。 典型的なサーバは、その情報を受け取り、path をセグメントへ、query をキー/値の組へとそれぞれ解析し、リクエストに応じるために実装特有の取り扱いを呼び出すであろう。 結果として、URI の全体、あるいは個別の構成要素を扱うサーバ実装についての共通のセキュリティ上の関心は、その URI 中の文字及びパーセントエンコーディングによって表現されるオクテットデータの適切な解釈である。

パーセントエンコードされたオクテットは、逆参照の処理の間のいずれかの時点でデコードされなければならない。 アプリケーションは、デコードされたオクテットが区切り子に間違えられるかもしれないので、オクテットをデコードする前に URI をその構成要素及び副構成酵素に分けなければならない。 URI 中のデータのセキュリティチェックは、オクテットをデコードした後に適用されるべきである。 しかし、%00 パーセントエンコーディング (NUL) は特別な取り扱いを必要とする必要があり、アプリケーションが構成要素中の生のデータを受け取る事を期待していなければそれは拒否されるべきである事に注意せよ。

URI path 解釈処理が後置{back-end} のファイルシステムあるいは関連するシステム機能の 使用にかかわる時には、特別な注意が払われるべきである。 ファイルシステムは、通常 "/", "\", ":", "[", "]" のような特殊文字や、また ".", "..", "...", "aux", "lpt" 等の特殊な装置名に操作上の意味を割り当てる。 いくつかの場合では、単にそのような名前の存在をテストする事でも、オペレーティングシステムが止まったり、関係ないシステムコールを呼び出す原因となり、サービス不能及び意図されないデータ転送にかかわる重大なセキュリティ上の懸念に至る。 この仕様書ではそのような重要な文字及び装置名を全て列挙する事は不可能である。 実装者はそれらのアプリケーションに取り付けられるであろう記憶装置の種類についての予約名及び文字を調査し、それに従って URI 構成要素から得られるデータの使用を制限すべきである。

7.4. 珍しい IP アドレス形式

IPv4address のための URI 構文は一般的なドット付き数字形式の IPv4 アドレスリテラルのみを認めているが、 URI を処理する多くの実装は文字列リテラルを実際の IP アドレスへと変換するために、gethostbyname() や inet_aton() のような、プラットホーム依存のシステムルーチンを利用する。 残念ながら、そのようなシステムルーチンは、しばしば Section 3.2.2 にて記述されるものよりはるかに大きな集合の形式を認め、そして処理を行う。

例えば、多くのアプリケーションは三つの番号のドット付き形式を認め、この場合、最後の部分が 16 ビットの量として解釈され、ネットワークアドレスの最も右 2 バイトに置かれる (例えば、クラス B ネットワーク)。 同様に、二つの番号のドット付きの形式は、最後の部分が 24 ビットの量として解釈され、ネットワークアドレスの最も右 3 バイトに置かれ (クラス A)、(ドットなしの) 単一の数字は 32 ビットの量として解釈され、直接ネットワークアドレスに格納される事を意味する。 更に混乱させる事に、いくつかの実装では、C 言語にて規定されるように、ドット付けされた部分が 10 進、8進、16 進として解釈される事も認める (すなわち、先行する 0x や 0X は 16 進を意味する; 先行する 0 は 8 進を意味する; さもなくば、その数は 10 進であると解釈される)。

これらの追加的 IP アドレス形式は、プラットホーム実装間の違いのため URI 構文では認められない。 しかし、アプリケーションが文字列リテラル形式で IP アドレスに基づくリソースへのアクセスをフィルタしようとするならば、それらはセキュリティ上の問題になるであろう。 このフィルタリングが実行される場合、リテラルは数値形式に変換され、数値に基づいてフィルタされるべきであり、文字列形式の先頭及び末尾からフィルタされるべきではない。

7.5. 機密性の高い情報

URI を生成するものは、秘密である事が意図されるようなユーザ名やパスワードを含む URI を提供すべきではない。 URI は、頻繁にブラウザに表示され、平文のブックマークに保存され、ユーザエージェントの履歴や中継アプリケーション (プロクシ) に記録される。 userinfo 構成要素中に現れるパスワードは推奨されず、'password' パラーメタが公である事が意図されるようなまれな場合以外では、エラーとみなされる (あるいは単に無視される) べきである。

7.6. 意味論的{Semantic} 攻撃

userinfo 副構成要素は滅多に使用されず、authority 構成要素中の host の前に現れるので、 実際にはノイズの後ろに隠れた異なるオーソリティを識別しているのにもかかわらず、ある (信頼できる) 命名オーソリティを識別するように見せる事によって人間のユーザを誤らせる事を意図した URI を構成するために使用する事ができる。 例えば

 ftp://cnn.example.com&story=breaking_news@10.0.0.1/top_story.htm

は、人間のユーザにその host が 'cnn.example.com' であると思わせるかもしれないが、実際には '10.0.0.1' である。 紛らわしい userinfo 副構成要素は、上の例よりはるかに長いものかもしれないので注意せよ。

上記のような、紛らわしい URI はソフトウェア自体への攻撃というよりむしろ URI の意味についてのユーザの先入観への攻撃である。 ユーザエージェントがそれらをレンダリングする時に、そのようなものがあるとして、例えば userinfo をレンダリングするのに異なる色あるいは色調を使用する事等、URI の様々な構成要素を区別する事によって、そのような攻撃の影響を減らす事ができるかもしれないが、しかしそれでも万能薬はない。 URI に基づく意味論攻撃に関する更なる情報は、[Siedzik] にて見つける事ができる。

8. IANA について

Section 3.1 の <scheme> によって定義されたような、URI スキーム名は、[BCP35] にて定義される手続きに従って IANA によって管理される登録済み名前空間を形成する。 この文書によって要求される IANA の行いはない。

9. 謝辞

この仕様書は、RFC 2396 [RFC2396], RFC 1808 [RFC1808], RFC 1738 [RFC1738] に由来するものである; 従って、それらの文書への謝辞は依然注がれるものである。 また、Robert M. Hinden, Brian E. Carpenter, Larry Masinter によって [RFC2732] にて定義されるように、host 構文における IPv6 リテラルの (訂正を含む) 更新を組み入れている。 加えて、Gisle Aas, Reese Anschultz, Daniel Barclay, Tim Bray, Mike Brown, Rob Cameron, Jeremy Carroll, Dan Connolly, Adam M. Costello, John Cowan, Jason Diamond, Martin Duerst, Stefan Eissing, Clive D.W. Feather, Al Gilman, Tony Hammond, Elliotte Harold, Pat Hayes, Henry Holtzman, Ian B. Jacobs, Michael Kay, John C. Klensin, Graham Klyne, Dan Kohn, Bruce Lilly, Andrew Main, Dave McAlpin, Ira McDonald, Michael Mealling, Ray Merkert, Stephen Pollei, Julian Reschke, Tomas Rokicki, Miles Sabin, Kai Schaetzl, Mark Thomson, Ronald Tschalaer, Norm Walsh, Marc Warne, Stuart Williams, Henry Zongaro 各氏による貢献に感謝を申し上げる。

10. 参照文献

10.1. 規約の一部としての参照

ASCII
American National Standards Institute, Coded Character Set -- 7-bit American Standard Code for Information Interchange, ANSI X3.4, 1986.
RFC2234
Crocker, D. and P. Overell, Augmented BNF for Syntax Specifications: ABNF, RFC 2234, November 1997.
STD63
Yergeau, F., UTF-8, a transformation format of ISO 10646, STD 63, RFC 3629, November 2003.
UCS
International Organization for Standardization, Information Technology - Universal Multiple-Octet Coded Character Set (UCS), ISO/IEC 10646:2003, December 2003.

10.2. 情報提供としての参照

BCP19
Freed, N. and J. Postel, IANA Charset Registration Procedures, BCP 19, RFC 2978, October 2000.
BCP35
Petke, R. and I. King, Registration Procedures for URL Scheme Names, BCP 35, RFC 2717, November 1999.
RFC0952
Harrenstien, K., Stahl, M., and E. Feinler, DoD Internet host table specification, RFC 952, October 1985.
RFC1034
Mockapetris, P., Domain names - concepts and facilities, STD 13, RFC 1034, November 1987.
RFC1123
Braden, R., Requirements for Internet Hosts - Application and Support, STD 3, RFC 1123, October 1989.
RFC1535
Gavron, E., A Security Problem and Proposed Correction With Widely Deployed DNS Software, RFC 1535, October 1993.
RFC1630
Berners-Lee, T., Universal Resource Identifiers in WWW: A Unifying Syntax for the Expression of Names and Addresses of Objects on the Network as used in the World-Wide Web, RFC 1630, June 1994.
RFC1736
Kunze, J., Functional Recommendations for Internet Resource Locators, RFC 1736, February 1995.
RFC1737
Sollins, K. and L. Masinter, Functional Requirements for Uniform Resource Names, RFC 1737, December 1994.
RFC1738
Berners-Lee, T., Masinter, L., and M. McCahill, Uniform Resource Locators (URL), RFC 1738, December 1994.
RFC1808
Fielding, R., Relative Uniform Resource Locators, RFC 1808, June 1995.
RFC2046
Freed, N. and N. Borenstein, Multipurpose Internet Mail Extensions (MIME) Part Two: Media Types, RFC 2046, November 1996.
RFC2141
Moats, R., URN Syntax, RFC 2141, May 1997.
RFC2396
Berners-Lee, T., Fielding, R., and L. Masinter, Uniform Resource Identifiers (URI): Generic Syntax, RFC 2396, August 1998.
RFC2518
Goland, Y., Whitehead, E., Faizi, A., Carter, S., and D. Jensen, HTTP Extensions for Distributed Authoring -- WEBDAV, RFC 2518, February 1999.
RFC2557
Palme, J., Hopmann, A., and N. Shelness, MIME Encapsulation of Aggregate Documents, such as HTML (MHTML), RFC 2557, March 1999.
RFC2718
Masinter, L., Alvestrand, H., Zigmond, D., and R. Petke, Guidelines for new URL Schemes, RFC 2718, November 1999.
RFC2732
Hinden, R., Carpenter, B., and L. Masinter, Format for Literal IPv6 Addresses in URL's, RFC 2732, December 1999.
RFC3305
Mealling, M. and R. Denenberg, Report from the Joint W3C/IETF URI Planning Interest Group: Uniform Resource Identifiers (URIs), URLs, and Uniform Resource Names (URNs): Clarifications and Recommendations, RFC 3305, August 2002.
RFC3490
Faltstrom, P., Hoffman, P., and A. Costello, Internationalizing Domain Names in Applications (IDNA), RFC 3490, March 2003.
RFC3513
Hinden, R. and S. Deering, Internet Protocol Version 6 (IPv6) Addressing Architecture, RFC 3513, April 2003.
Siedzik
Siedzik, R., Semantic Attacks: What's in a URL?, April 2001, http://www.giac.org/practical/gsec/Richard_Siedzik_GSEC.pdf.

付録 A. URI のために収集された ABNF

 URI           = scheme ":" hier-part [ "?" query ] [ "#" fragment ]

 hier-part     = "//" authority path-abempty
               / path-absolute
               / path-rootless
               / path-empty

 URI-reference = URI / relative-ref

 absolute-URI  = scheme ":" hier-part [ "?" query ]

 relative-ref  = relative-part [ "?" query ] [ "#" fragment ]

 relative-part = "//" authority path-abempty
               / path-absolute
               / path-noscheme
               / path-empty

 scheme        = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." )

 authority     = [ userinfo "@" ] host [ ":" port ]
 userinfo      = *( unreserved / pct-encoded / sub-delims / ":" )
 host          = IP-literal / IPv4address / reg-name
 port          = *DIGIT

 IP-literal    = "[" ( IPv6address / IPvFuture  ) "]"

 IPvFuture     = "v" 1*HEXDIG "." 1*( unreserved / sub-delims / ":" )

 IPv6address   =                            6( h16 ":" ) ls32
               /                       "::" 5( h16 ":" ) ls32
               / [               h16 ] "::" 4( h16 ":" ) ls32
               / [ *1( h16 ":" ) h16 ] "::" 3( h16 ":" ) ls32
               / [ *2( h16 ":" ) h16 ] "::" 2( h16 ":" ) ls32
               / [ *3( h16 ":" ) h16 ] "::"    h16 ":"   ls32
               / [ *4( h16 ":" ) h16 ] "::"              ls32
               / [ *5( h16 ":" ) h16 ] "::"              h16
               / [ *6( h16 ":" ) h16 ] "::"

 h16           = 1*4HEXDIG
 ls32          = ( h16 ":" h16 ) / IPv4address
 IPv4address   = dec-octet "." dec-octet "." dec-octet "." dec-octet

 dec-octet     = DIGIT                 ; 0-9
               / %x31-39 DIGIT         ; 10-99
               / "1" 2DIGIT            ; 100-199
               / "2" %x30-34 DIGIT     ; 200-249
               / "25" %x30-35          ; 250-255

 reg-name      = *( unreserved / pct-encoded / sub-delims )

 path          = path-abempty    ; begins with "/" or is empty
               / path-absolute   ; begins with "/" but not "//"
               / path-noscheme   ; begins with a non-colon segment
               / path-rootless   ; begins with a segment
               / path-empty      ; zero characters

 path-abempty  = *( "/" segment )
 path-absolute = "/" [ segment-nz *( "/" segment ) ]
 path-noscheme = segment-nz-nc *( "/" segment )
 path-rootless = segment-nz *( "/" segment )
 path-empty    = 0<pchar>

 segment       = *pchar
 segment-nz    = 1*pchar
 segment-nz-nc = 1*( unreserved / pct-encoded / sub-delims / "@" )
               ; non-zero-length segment without any colon ":"

 pchar         = unreserved / pct-encoded / sub-delims / ":" / "@"

 query         = *( pchar / "/" / "?" )

 fragment      = *( pchar / "/" / "?" )

 pct-encoded   = "%" HEXDIG HEXDIG

 unreserved    = ALPHA / DIGIT / "-" / "." / "_" / "~"
 reserved      = gen-delims / sub-delims
 gen-delims    = ":" / "/" / "?" / "#" / "[" / "]" / "@"
 sub-delims    = "!" / "$" / "&" / "'" / "(" / ")"
               / "*" / "+" / "," / ";" / "="

付録 B. 正規表現による URI 参照の解析

"first-match-wins" アルゴリズムは、POSIX 正規表現によって使用される "貪欲な{greedy}" 曖昧さ解消の手法と同じなので、URI 参照の潜在的な五つの構成要素を解析するために正規表現を使用する事は、自然であり、普通の事である。

以下の行は、整形された URI 参照をその構成要素に分解するための正規表現である。

 ^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?
  12            3  4          5       6  7        8 9

上記二行目における数は、単に読み易くするためのものである; これらは、各副表現 (すなわち、それぞれの対である丸括弧) のための参照点を示す。 我々は、副表現 <n> に合致する値を $<n> として示す。 例えば、上の表現を

 http://www.ics.uci.edu/pub/ietf/uri/#Related

に適合させると、下のような副表現に一致する事になる:

 $1 = http:
 $2 = http
 $3 = //www.ics.uci.edu
 $4 = www.ics.uci.edu
 $5 = /pub/ietf/uri/
 $6 = <未定義>
 $7 = <未定義>
 $8 = #Related
 $9 = Related

ここで、<未定義> とは、上の例における query 構成要素の場合のように、その構成要素が存在していない事を表す。

 scheme    = $2
 authority = $4
 path      = $5
 query     = $7
 fragment  = $9

逆の手順を行う事で、我々は Section 5.3 のアルゴリズムを使用する事によってその構成要素から URI 参照を再生成する事ができる。

付録 C. 状況内の URI の範囲設定

URI は、しばしばそれらの解釈についての明確な状況を提供しない形式を通して転送される。 例えば、多くの場合、URI がプレーンテキスト内に含まれる時にある; この例には、電子メールや USENET ニュースにて送られるテキスト、及び印刷用紙上のテキストを含む。 そのような場合、テキストの残り、及び特に URI の一部と間違えられるかもしれない句読点から URI を区切る事ができる事が重要である。

実際には、URI は 様々な方法で区切られるが、通常は "http://example.com/" という二重引用符、角括弧 <http://example.com/>、あるいは空白を使用する事により直接記述される:

 http://example.com/

これらの包む物{wrappers} は、URI の一部を形成するものではない。

ある場面では、行をまたぐ長い URI を改行するために余分な空白 (スペース、改行、タブ等) が加えられなければならないかもしれない。 URI が抽出される時、空白は無視されるべきである。

ハイフン ("-") 文字の後には空白を導入すべきではない。 いくつかのタイプセッタやプリンタが改行する時に行末に (誤って) ハイフンを導入するかもしれないので、ハイフンのすぐ後に改行を含んでいる URI を解釈するものは、改行のまわりの全ての空白を無視すべきであり、またハイフンが実際に URI の一部であるかもしれない事を意識すべきである。

各 URI のまわりに <> 山括弧を使用する事は、空白が埋め込まれる参照を区切るための形式なので、特に推奨される。

"URL:" という接頭語 (その後ろにスペースがあるなしにかかわらず) は、他の括弧を呼び出すものから URI を区別するための方法として以前推奨されていたが、実際には通常使用されないし、またもはや推奨もされない。

堅牢性{robustness} のために、ユーザによって打ち込まれた URI を受け入れるソフトウェアは、区切り子と埋め込まれた空白の両方を認識し、また取り除こうとするべきである。

例えば、以下のテキスト

 Yes, Jim, I found it under "http://www.w3.org/Addressing/",
 but you can probably pick it up from <ftp://foo.example.
 com/rfc/>.  Note the warning in <http://www.ics.uci.edu/pub/
 ietf/uri/historical.html#WARNING>.

は、以下の URI 参照を含む

 http://www.w3.org/Addressing/
 ftp://foo.example.com/rfc/
 http://www.ics.uci.edu/pub/ietf/uri/historical.html#WARNING

付録 D. RFC 2396. からの変更点

D.1. 追加点

一つの一般的な用語、すなわち "任意の fragment を持つ絶対 URI" の使用法に対応するために URI のための ABNF 規則が導入されている。

authority 構成要素の host 部分のための取り得る識別子のリストとして、[RFC2732] にて記述されるように、IP リテラルの将来のバージョンを見越して予約済み文字に "[" と "]"、及びバージョンフラグを追加した、IPv6 (及びそれ以降) リテラルが追加されている。 角括弧は、現在 authority 構成要素中で予約済みと規定されており、host 中の IP リテラルのための区切り子としてそれらを使用する事以外は認められない。 path, query, fragment の技術的定義を変える事無くこの変更を行うため、これらの規則は直接認められる文字を指定するよう再定義された。

[RFC2732] は IPv6 リテラルアドレスの定義のために [RFC3513] に従うが、残念ながら、IPv6address の ABNF 記述が欠けているので、 我々は [RFC3513] の Section 2.2 によって定義されたテキスト表現に合致する IPv6address のための新たな ABNF 規則を作成した。 同様に、IPv4address の定義は、それぞれの 10 進オクテットを範囲 0-255 に制限するように改良された。

Section 6 の URI の正常化と比較は、Tim Bray からのアドバイスの提供、及び W3C Technical Architecture Group 内の議論を用いて、完全に書き直され、また拡張された。

D.2. 修正点

RFC 2396 の特別な BNF 構文は [RFC2234] の ABNF に置き換えられた。 この変更により、以前下線文字を含んでいた全ての規則名を代わりにダッシュを用いて改名する必要があった。 加えて、全体の文法をより理解しやすくするために、多くの構文規則が削除、あるいは簡素化された。 廃案となった文法規則を参照する仕様書では、以下の表に従ってそれらの規則を置き換える事によって理解されるであろう:

以前の規則 変更されたもの
absoluteURI absolute-URI
relativeURI relative-part [ "?" query ]
hier_part ( "//" authority path-abempty / path-absolute ) [ "?" query ]
opaque_part path-rootless [ "?" query ]
net_path "//" authority path-abempty
abs_path path-absolute
rel_path path-rootless
rel_segment segment-nz-nc
reg_name reg-name
server authority
hostport host [ ":" port ]
hostname reg-name
path_segments path-abempty
param *<pchar excluding ";">
uric unreserved / pct-encoded / ";" / "?" / ":" / "@" / "&" / "=" / "+" / "$" / "," / "/"
uric_no_slash unreserved / pct-encoded / ";" / "?" / ":" / "@" / "&" / "=" / "+" / "$" / ","
mark "-" / "_" / "." / "!" / "~" / "*" / "'" / "(" / ")"
escaped pct-encoded
hex HEXDIG
alphanum ALPHA / DIGIT

スキーム特有の構文の定義について、上記の廃案となった規則の使用は非推奨とする。

Section 2は、文字についてであるが、どんな文字が予約されているか、それらはいつ予約されるのか、そして一般の構文によって区切り子として使用されていない時でさえ、何故それらは予約されるのかを表すために書き直された。 通常デコードすると安全でない記号文字には、感嘆符 ("!")、アスタリスク ("*")、一重引用符 ("'quot;)、両丸括弧 ("(quot; と quot;)quot;) があるが、予約済と非予約の区別を明確にするために、そして願わくばスキーム設計者の最も一般的な疑問に答えられるように、予約されている集合を動かした。 同様に、パーセントエンコードされた文字の節も書き換えられ、URI を正規化するものは現在あらゆるパーセントエンコードされたオクテットを対応する非予約文字へとデコードするための許可が与えられる 一般に、"escaped" と "unescaped" という用語は、他のエスケープメカニズムの形式への混乱を減らすために、それぞれ、"percent-encoded" と "percent-decode" に置き換えられる。

URI と URI 参照のための ABNF は、LALR パーサにより扱いやすくさせるために、そして複雑さを減らすために再設計された。 結果として、uric, uric_no_slash, opaque_part, net_path, abs_path, rel_path, path_segments, rel_segment, mark の各規則を伴う、構文記述の位置決めの形式は削除された。 全ての "不明な{opaque}" URI への参照は、どのように path 構成要素が階層構造に隠されているであろうかについてのより良い記述に置き換えられた。 relativeURI の規則は、それらが URI の部分集合であるかどうかについての不要な混乱を避けるために relative-ref に置き換えられた。 URI 参照の解析を URI とみなすか、あるいは最初のセグメント内のコロンを含む relative-ref とみなすかの曖昧さは、五つの異なる path 合致規則の使用により排除された。

fragment 識別子は、一般的な構文構成要素の節へ戻され、URI 及び relative-ref 規則内に復帰したが、依然 absolute-URI からは除外される。 数字記号 ("#") 文字は、fragment の構文を再統合した結果、予約集合へと復帰した。

ABNF は、path 構成要素が空である事を認めるように修正された。 またこれは、実際に "dav:" 名前空間 [RFC2518] や多くの WWW ブラウザ実装によって内部的に使用されている "about:" スキームとして実在している、 "scheme:" の後に何もないような absolute-URI を認める。 authority と path の間の境界に関する曖昧さは、五つの異なる path 合致規則の使用により排除された。

一般的構文を使用するレジストリに基づいた命名機関{naming authorities} は、現在 host の規則の中で定義される。 この変更によって、提供されたどんな名前も単にローカルの名前解決メカニズムに渡しているような、現在の実装が仕様書に合致できるようになる。 また、それはその場で DNS 名前形式を再指定する必要性も取り除く。 更に、国際化ドメイン名が URI 内で提供され、URI 処理の上のアプリケーション層において元来の文字エンコーディングにて処理され、UTF-8 文字エンコーディングにおける登録名として IDNA ライブラリに渡される事ができる必要があるので、host 構成要素がパーセントエンコードされたオクテットを含める事を認める。 server, hostport, hostname, domainlabel, toplabel, alphanum の規則は削除された。

[RFC2396] の相対的参照の解決は、明快さを改良し、以下の問題を修正するために、この改訂で擬似コードをもって書き直された:

索引

(省略)

筆者のアドレス

 Tim Berners-Lee
 World Wide Web Consortium
 Massachusetts Institute of Technology
 77 Massachusetts Avenue
 Cambridge, MA  02139
 USA

 Phone: +1-617-253-5702
 Fax:   +1-617-258-5999
 EMail: timbl@w3.org
 URI:   http://www.w3.org/People/Berners-Lee/


 Roy T. Fielding
 Day Software
 5251 California Ave., Suite 110
 Irvine, CA  92617
 USA

 Phone: +1-949-679-2960
 Fax:   +1-949-679-2972
 EMail: fielding@gbiv.com
 URI:   http://roy.gbiv.com/


 Larry Masinter
 Adobe Systems Incorporated
 345 Park Ave
 San Jose, CA  95110
 USA

 Phone: +1-408-536-3024
 EMail: LMM@acm.org
 URI:   http://larry.masinter.net/

著作権表示全文

Copyright © The Internet Society (2005). All Rights Reserved.

この文書は、BCP 78 に含まれる権利、許可、制限に従い、その中で明示されるものを除いて、著者が全ての権利を保持する。

この文書とここに含まれた情報は、"そのまま {AS IS}" である事を基に提供され、投稿者や、(もしいるならば) その人物が代表する、あるいはその人物を後援する組織、インターネット学会、及び IETF は、この中の情報の使用が、商用利用及び特定用途においていかなる権利もいかなる暗黙的保障も侵害していないという保障への制限を含め、明示的に又は暗黙的に、全ての保障を放棄する

知的所有権

IETF は、この文書内に記述された技術の実装や使用に付随して主張されるいかなる知的所有権あるいは他の権利の正当性や範囲に関して、あるいはその様な権利の下でいかなる許可が利用可能であり、また利用不可能であるかの範囲に関して、いかなる立場もとらない; すなわち、そのような権利を識別するためのいかなる独立的調査を行った事も明言しない。 IETF 文書内の権利に関する IETF の手続き上の情報は、BCP 78 と BCP 79 にて見つける事ができる。

IETF 事務局による IPR ディスクロージャのコピーや、利用可能とされるようなライセンスの保証や、この仕様書の実装者や利用者によってそのような所有者の権利の使用のために一般的なライセンスや許可を得るためになされた試みの結果は、http://www.ietf.org/ipr にある IETF オンライン IPR レポジトリから得る事ができる。

IETF は、この標準を実装するために必要な技術をカバーするためのあらゆる著作権、特許、特許の出願、あるいは他の所有権について明らかにする事に興味を持つ団体を募集している。 どうか IETF の ietf-ipr@ietf.org にその情報をお寄せ頂きたい。

謝辞

RFC Editer 機構の資金は、現在インターネット学会から提供されている。


#TOP
Copyright © 1999-2008 橋本英彦 (H-Hash), All Rights Reserved.