開発者ツール · URL エンコーダーとデコーダー
URL の構造: スキーム、権限、パス、クエリ、フラグメントの説明
· 背景
URL 構造 ウェブ標準 開発者ツール
パーセント エンコーディングの決定は、URL のどの部分に文字が含まれるかによって決まります。この投稿では、RFC から 3986 の 5 つのコンポーネントに名前を付け、各区切り文字の意味と、フラグメントがサーバーに到達しない理由を示します。
なぜ同じ # がある場所では問題なく、別の場所ではリンクが破壊されるのか — キャラクターの問題ではなくコンポーネントの問題
URL 内のハッシュ文字 (#) は、出現する場所によってまったく異なる意味を持ちます。 ?search=C%23sharp のようなクエリ文字列値の内部では、安全のために %23 にエンコードする必要があります。 https://example.com/page#section, のような URL の末尾では、フラグメント区切り文字と、それ以降のすべてがフラグメントであることがマークされます。 1 つの文字、2 つのコンテキスト、2 つの異なる意味。このため、エンコードの決定は、URL のどの部分を処理しているのかを知ることに依存します。
クエスチョンマーク(?)にも二面性があります。パスまたはクエリ値内で、データとして表示するには、%3F としてエンコードする必要があります。パスとクエリ文字列の間のリテラル文字として、構造構文となります。これら 5 つのコンポーネント (スキーム、権限、パス、クエリ、フラグメント) を理解することは、正しい URL 処理の基礎です。
5 つのコンポーネント: スキーム、権限、パス、クエリ、フラグメント、およびそれらを区切る区切り文字
RFC 3986 では、URL がスキーム、権限、パス、クエリ、フラグメントの 5 つのコンポーネントを特定の区切り文字で区切ったものとして正式に定義しています。最初にスキームがあり、その後に ://,、次に権限、次に /,、パス、次に ?、クエリ、#、フラグメントが続きます。すべてのコンポーネントがすべての URL に表示されるわけではありません。最小限の URL には、「mailto:user@example.com」など、スキームとパスのみが含まれる場合があります。完全な URL には 5 つすべてが含まれます。
各コンポーネントには独自の構文規則があります。コロンはスキームで、スラッシュはパスで、アンパサンドはクエリで予約されています。予約文字は、データとして表示されるときにエンコードが必要です。パス値のスラッシュは %2F になります。
権限内 - ユーザー情報、ホスト、ポート、および @ と : がそこで予約されている理由
権限コンポーネントには、リソースのネットワーク アドレス (ユーザー名、パスワード、ホスト名、ポート) が含まれています。形式は [userinfo@]host[:port] です。ユーザー情報とホストは @ で区切られます。ホストとポートは: で区切られます。これらの @ および : 文字は、これらのサブコンポーネントを区切るための権限内で予約されています。 @ 記号を含むユーザー名がある場合は、連結する前にパーセントでエンコードする必要があります。たとえば、ユーザー名としての「user@email.com:password」は、最後の @ の前では「user%40email.com:password」になります。
ホスト名には、example.com のような登録済みドメイン、192.0.2.1 のようなドット付き 10 進数の IP アドレス、または [::1] のような括弧で囲まれた IPv6 アドレスを指定できます。ポートはオプションです。省略した場合、スキームによってデフォルトが決定されます (http の場合は 80、https の場合は 443 など)。 userinfo 部分は最近の URL ではほとんど使用されませんが、構文の一部として残ります。
パス セグメントと / の意味 — 階層構造とドット セグメントの解決
パスは、スラッシュで区切られた一連のセグメントです。パス /a/b/c には、a、b、c の 3 つのセグメントがあります。各セグメントには、予約されていない文字、パーセントでエンコードされた文字、またはこのコンテキストでは安全な特定の予約文字を含めることができます。セグメント区切り文字との混同を避けるために、セグメント内のスラッシュは %2F としてエンコードする必要があります。パスは階層的です。これは a が場所であることを暗示しており、その場合は a/b の方がより具体的です。
パスは特殊なドット セグメントもサポートしています。1 つのドット (.) は「現在のディレクトリ」を意味し、2 つのドット (..) は「親ディレクトリ」を意味します。 ../../etc/passwd のようなパスは上向きに解決されます。最新の URL と HTTP ではこれらの使用は避けられていますが、構文には存在します。リテラルのドットまたはダブルドットを含むパス セグメントは、リテラルのドットの意味が意図されていない場合、パーセント エンコードする必要があります。
クエリとフラグメント — キーと値の規則、およびフラグメントがブラウザーに留まる理由
クエリ文字列はパスに従い、? で始まります。これは伝統的に & で区切られた一連の key=value ペアですが、構文は実際には構造化されておらず、クエリには何でも含めることができます。 & または = を含む値がある場合、区切り文字と間違われないように、それらの文字をパーセントでエンコードする必要があります。クエリはサーバーに送信されます。それをどうするかはサーバーが決定します。
フラグメントはクエリの後に続き、# で始まります。 # 以降はすべてフラグメントであり、サーバーに到達することはありません。ブラウザはフラグメントをローカルで処理し、通常は名前付きアンカーにジャンプしたり、単一ページ アプリケーション内の状態を示したりします。フラグメントはサーバーに到達しないため、異なるフラグメントを持つ URL は同じリソースを指していると見なされます。
実用的な例: 現実世界の長い URL を分析する — すべてのコンポーネントとすべての区切り文字にラベルを付ける
URL「https://user:pass@example.com:8080/path/to/page?search=hello&sort=date#results". を取得します。スキームは https です。権限は user:pass@example.com:8080 で、userinfo (user:pass)、host (example.com)、および port (8080) に分割されます。パスは /path/to/page, で、セグメントは path、to、page です。クエリは search=hello&sort=date で、2 つが含まれます。フラグメントが結果です。この URL を URL エンコーダとデコーダに入力すると、ツールが各コンポーネントにどのようにラベルを付け、エンコードするかを確認できます。
?search=R&D のように検索に & が含まれる場合、正しくエンコードすると ?search=R%26D になります。パーセントエンコードされた文字はテキスト内に視覚的な境界を作成しないため、正しく解析するには慎重なエンコードとデコードが不可欠です。
これでカバーされないもの — 相対参照解決と mailto: や data: などの特別なスキーム
「../page"」や「?query=value」などの相対参照は HTML 内で有効であり、現在のドキュメントに対して相対的に解釈されますが、独自の別個の解決ルールがあります。 mailto:、data:、file: などの特別なスキームはまったく異なるルールに従い、標準の絶対 URL ではありません。
この投稿では、インスペクターによって示された標準の絶対 URL 構造のみに焦点を当てます。相対参照はコンポーネントを解釈する前にベース URL を必要としますが、mailto や data などのスキームは同じ権限とパスの形状を共有しません。これらのケースを分離しておくと、HTTPS アドレスから学習したルールが、異なる区切り文字、解決手順、またはトランスポート動作を使用する構文に盲目的に適用されるのを防ぐことができます。
要点: エンコードする前にコンポーネントを理解する — URL エンコーダーとデコーダーの単一値モードと全体アドレス モードがこの構造にどのようにマッピングされるか
エンコードしているコンポーネントによって、エスケープが必要な文字と安全な文字が決まります。スラッシュはパス内のリテラル構文であるため、値内のスラッシュは %2F である必要があります。クエリでは、& と = が値に含まれる場合はエンコードする必要があります。 URL エンコーダとデコーダには、単一の値をエンコードする「コンポーネント」と完全な URL をエンコードする「全体アドレス」の 2 つのモードがあります。部分を連結して URL を構築する場合は、コンポーネント モードを使用します。既存の URL を確認するには、完全アドレス モードを使用します。
5 つのコンポーネントとその区切り文字を知っておくと、エンコード タスクに遭遇するたびに正しく選択できるようになります。