URI完全ガイド:構成要素・URL/URNの違い・正規化と実務上の注意(RFC3986準拠)

URIとは

URI(Uniform Resource Identifier)は、インターネット上の資源(リソース)を一意に識別するための文字列の仕組みです。単に「住所」のようにリソースを指し示す役割を持ちます。Webブラウザで使う「http://example.com/index.html」や「mailto:info@example.com」、またファイルやデータを直接記述するdata URIなど、さまざまな形式がURIとして扱われます。

歴史と標準化

  • 初期の概念は「URL(Uniform Resource Locator)」として導入され、RFC 1738(1994年)が代表的です。

  • その後、リソースを「識別」するというより一般的な概念を表すために「URI」という上位概念が定められ、RFC 2396(1998年)により汎用構文が提示されました。

  • 現在の事実上の標準は RFC 3986(2005年)で、URIの汎用構文、正規化や参照(相対URIの解決)などを定義しています。

  • URN(Uniform Resource Name)の構文については RFC 2141(1997)から RFC 8141(2017年)へと更新されており、国際化を考慮したIRI(Internationalized Resource Identifier)は RFC 3987(2005年)で定義されています。

URIの構成要素(汎用構文)

RFC 3986 に従うと、典型的なURIは次のような構成要素を持ちます(角括弧は省略)。

  • scheme:プロトコル名やスキーム(例:http, https, ftp, mailto, data)。末尾にコロンが付く(例:http:)。スキーム名は大文字・小文字を区別しない。

  • authority:認証情報userinfo(任意)、ホスト名、ポート番号を含む部分(例:user:pass@example.com:8080)。"//"で始まることが多い。

  • path:リソースの位置を示すパス(例:/docs/index.html)。サーバの設定により大文字小文字の扱いが異なる点に注意。

  • query:クエリ文字列(?から始まる)。サーバやアプリケーションでパラメータとして解釈される。

  • fragment:フラグメント(#以降)。URI参照のクライアント側の部分(ブラウザ内の文書内位置など)で、サーバへは送信されない。

URI・URL・URN の違い

しばしば混同されますが、簡潔にまとめると次の通りです。

  • URI:リソースを一意に識別する総称(umbrella term)。

  • URL(Locator):リソースの位置(アクセス方法)を示すURIの一種。例:Web上のファイルにアクセスするためのhttp/httpsなど。

  • URN(Name):恒久的な名前(識別子)を示すURIの一種で、必ずしも位置を表さない(例:urn:isbn:0451450523)。

RFC 3986 では「URI」が包括的な用語として扱われ、URL/URNは用途や意味合いで区別されます。実務では「URL」という語が一般的に使われ続けていますが、技術文書や標準では「URI」を使うのが正しい場面が多いです。

エンコーディングと国際化(IRI)

URI は基本的に英数字と一部の記号のみを安全に使えるため、それ以外の文字(日本語など)はエンコードが必要です。これを「パーセントエンコーディング(%NN)」と呼びます(RFC 3986 セクション2.1)。

国際化された文字(非ASCII)を扱うために IRI(RFC 3987)が導入されており、人間に見やすい表記を可能にします。ただし実際の通信やプロトコル処理では多くの場合 IRI を UTF-8 に正規化し、必要に応じてパーセントエンコードしたり、ドメイン名は Punycode(IDN: 国際化ドメイン名)へ変換したりします。

相対URIと基準(base)

HTMLやXMLなどでは相対URIがよく使われます。相対URIは基準となる「基底URI(base URI)」に対して解決(正規化)されて絶対URIになります。RFC 3986 の Section 5 が相対参照の解決方法を定めています。HTMLでは <base href="..."> 要素が基底URIを指定するために使えます。

正規化・正準化(Normalization)

同じ資源を指す複数のURI表記が存在するとき、比較やキャッシュ、セキュリティ判定で問題が生じます。正規化とは次のような処理を指します:

  • スキーム名やホスト名の小文字化(これらは大文字小文字を区別しない)

  • デフォルトポートの削除(例:http ポート80 を省略)

  • パーセントエンコーディングの正規化(%7E と ~ 等)

  • パスのドットセグメント("./", "../")の解決

ただしパスやクエリの大文字小文字の扱いはサーバ側の実装に依存するため、安易な小文字化は危険です。

実務上の注意点・セキュリティ

  • フラグメント(#以降)はサーバへ送られないため、サーバ側で機密情報をフラグメントで渡す設計は避けるべきです。

  • オープンリダイレクトや不適切な正規化を悪用した攻撃(ディレクトリ・トラバーサル、正規化攻撃)に注意する。URIの検証は慎重に行う。

  • IDN(国際化ドメイン名)を用いたホモグラフ攻撃(見た目が似た文字を使ったフィッシング)に注意。必要なら Punycode 表記を表示するなどの対策を検討。

  • データURI(data:)やjavascript: スキームは XSS のリスクを高めうる。ユーザー入力を直接URIとして扱うときはサニタイズが必須。

  • URI長やブラウザのURL長制限(実際にはブラウザやサーバーにより異なる。IIS/IEでは過去に 2083 文字などの制限が知られているが、現代の実装でも長さには実用的制限がある)を考慮する。

開発・運用でのベストプラクティス

  • 資源の識別と位置(名前とロケータ)を明確に分ける。恒久的な識別子(URNや自社の識別体系)と実際の配布URLを分離できる設計が望ましい。

  • URIを生成・処理するライブラリ(標準ライブラリ、WHATWG URL API、URIパーサー)を利用し、独自実装は避ける。

  • ユーザー入力を含むURIは必ずエンコードし、不正なスキーム(javascript: など)をホワイトリストで制限する。

  • 公開APIではURIの形式(スキーマ、パス規則、エンコーディング)をドキュメント化して互換性を保つ。

  • クエリパラメータ順序の取り扱いや同値比較ルールを定義してキャッシュや署名検証の不整合を防ぐ。

具体例(簡単なパターン)

  • 絶対URI:https://example.com:443/path/page.html?x=1#section

  • 相対URI:../images/photo.png — 基底URIに対して解決される。

  • URN:urn:isbn:0451450523

  • データURI例:data:text/plain;charset=utf-8,Hello%20World

  • メールリンク:mailto:info@example.com?subject=Hello%20World

まとめ

URI はインターネット上で資源を識別するための基礎的かつ重要な仕組みです。技術仕様(RFC 3986)に従い、正しいエンコーディング、正規化、相対参照の取り扱いを行うことが、安全で互換性のある設計に不可欠です。開発時には標準ライブラリやブラウザの仕様(WHATWG URL など)を活用し、セキュリティリスク(XSS、ホモグラフ、リダイレクト)に対する対策を講じることを推奨します。

参考文献