日本語

開発者ツール · URL エンコーダーとデコーダー

パーセントエンコーディングの仕組み: 文字から UTF-8 バイト、そして %XX シーケンスまで

· 仕組み

URLエンコーディング utf-8 パーセントエンコーディング 開発者

UTF-8 エンコード ステップを通じてパーセント エンコードされた 16 進数シーケンスにマップされた文字コード
オリジナル ToolAcre ベクトル イラスト

パーセントエンコーディングは文字をエンコードしません。バイトをエンコードします。この投稿では、文字がどのように UTF-8 バイトになり、その後 16 進数のペアになるのか、また、アクセント付き文字が 2 つの %XX グループを必要とするのに対し、絵文字は 4 つ必要となる理由を示します。

'é' が %E9 ではなく %C3%A9 になる理由 - その下のバイト層を明らかにする観察

若手開発者が URL 内に %C3%A9 を見た場合、パーセント エンコーディングは文字ではなくバイトに作用します。文字 é は 1 バイトではありません。 UTF-8 は、C3 A9 の 2 つにエンコードします。 RFC 3986 のパーセント エンコーディング ルールは単純です。各バイトをパーセント記号とそれに続く 2 つの 16 進数としてエンコードします。この違いにより、説明は神秘的なものから論理的なものへと変わります。

パーセント エンコーディングを理解するには、UTF-8 を理解する必要があります。テキストは、文字エンコーディングを使用してバイトに変換する必要があります。 UTF-8 は URL と Web の標準です。文字を可変長のバイト シーケンスとして表現します。ASCII は 1 バイト、アクセント付き文字は 2 バイト、絵文字は 4 バイトを使用します。各ステージは個別です: 文字、Unicode コード ポイント、UTF-8 バイト、次に %XX ペア。バイトを理解せずに 16 進数にスキップすることは、要点を逸脱します。

RFC 3986 のパーセント エンコーディング ルール — 1 % の後にバイトごとに 2 つの 16 進数が続き、大文字が推奨されます

RFC 3986 では、各バイトをパーセントとしてエンコードし、その後に 2 つの大文字の 16 進数を続けるという 1 つのルールが定義されています。エンコードを必要としない予約されていない文字は、文字、数字、ハイフン、アンダースコア、ピリオド、チルダです。それ以外はすべてエンコードする必要があります。スペースは %20、スラッシュは %2F、パーセント記号は %25 になります。これにより、クエリ値内の特殊文字が URL 構造を破壊するのを防ぎます。

スペースはバイト 0x20 としてエンコードされ、%20 になります。スラッシュは 0x2F で、%2F になります。これらは 1 バイトを必要とする ASCII 文字です。アクセント付きの文字と絵文字は異なります。パーセント記号は %25 になります。コロンなどの予約された区切り文字は、構造を維持するためにエンコードされます。これにより、クエリ パラメーターに埋め込まれたアンパサンドまたはイコールによって解析が中断されるのを防ぎます。各バイトは%HHになります。

UTF-8 を想定される文字セットとして — 最新の URL が UTF-8 である理由と従来の例外はどこにあるのか

UTF-8 は可変長エンコーディングを使用します。コードポイント 0 から 127 までの ASCII は 1 バイトです。 128 から 2047 までの文字 (アクセント付きラテン文字を含む) は 2 バイトです。東アジアの文字で一般的な 2048 から 65535 までの文字は 3 バイトです。 65535 より上の文字は、ほとんどの絵文字を含めて 4 バイトです。各バイトには、後に続くバイト数を示すビットが接頭辞として付けられます。

アクセント付き文字 é は Unicode コード ポイント U+00E9 です。 UTF-8 は、0xC3 と 0xA9 の 2 バイトとしてエンコードします。パーセントエンコーディングでは %C3%A9 が生成されます。ドイツ語の ü (U+00FC) は 0xC3 0xBC としてエンコードされ、%C3%BC になります。スペイン語 ñ (U+00F1) は 0xC3 0xB1 としてエンコードされ、%C3%B1 になります。パターンは一貫しています。最初のバイトは 2 バイト シーケンスを示します。アクセント付きの 1 文字は、エンコーディングで 6 文字ずつ拡張されます。

作業例: 'café 😀' をバイトごとにエンコード — コードポイント、UTF-8 バイト、および結果の文字列

絵文字はバイト層を明確にします。親指を立てた絵文字 👍 は、コード ポイント U+1F44D です。 UTF-8 は、F0 9F 91 8D の 4 バイトとしてエンコードします。パーセントエンコーディングでは、%F0%9F%918D (1 つのシンボルに対して 12 文字) が生成されます。スマイリー 😀 (U+1F600) は F0 9F 98 80 としてエンコードされ、%F0%9F%9880 になります。 4 バイトのシーケンスは 12 パーセントでエンコードされた文字になります。

混合テキストは、バイトを理解することが重要である理由を示しています。 「カフェ 😀」というフレーズには、普通の ASCII、アクセント、絵文字が含まれています。文字 c、a、f は、63、61、66 としてエンコードされます。 é は C3 A9 としてエンコードされます。スペースは 20 としてエンコードされます。絵文字は F0 9F 98 80 としてエンコードされます。結果は「caf%C3%A9%20%F0%9F%9880」になります。どのバイトにエンコードが必要かを理解すると、出力が予測可能になります。

逆デコード - %XX グループをバイトに収集し、それを UTF-8 として解釈します。

デコードすると、プロセスが逆になります。デコーダは %XX ペアをスキャンし、それらをバイト値に収集します。 %C3%A9 を参照して、バイト C3 と A9 を抽出します。 UTF-8 デコードでは、これらは文字 é として解釈されます。 %C3 だけなど、シーケンスが不完全な場合、結果はエラーになります。デコーダは、UTF-8 プレフィックス ビットから、C3 に 2 番目のバイトが必要であることを認識します。

16 進数では大文字と小文字は関係ありません。 %C3%A9 と %c3%a9 は同じようにデコードされます。 RFC では大文字も小文字も許可されていますが、大文字の方が優先されます。ただし、文字の大文字と小文字は区別されます。é (%C3%A9 として) は É (%C3%89 として) と同じではありません。 URL 比較ではパーセント エンコーディングを正規化する必要があります。そうしないと、同一のリソースが異なるものとして扱われる危険があります。フレームワークはキャッシュする前に正規化します。

16 進数では大文字と小文字が区別されないが、他の場所では大文字と小文字が区別される理由 — 正規化ルールと URL 比較

RFC 3986 には、ドメイン名の Punycode と送信のフォーム エンコーディングが別のルールとして記載されています。 Punycode は、DNS 互換性を確保するために、非 ASCII ドメイン名をパーセント記号なしでエンコードします。ドメイン 😀.example は「xn--js8h.example」になります。フォーム エンコーディングはパーセント エンコーディングを変更しますが、1 つの例外があります。スペースは %20 ではなくプラス記号になります。 application/x-www-form-urlencoded として送信されたフォームでは、スペースにプラスを使用します。

URL エンコーダ ツールは、コンポーネント エンコード、URL 全体エンコード、フォーム エンコードの 3 つのモードをすべて表示します。 encodeURIComponent を使用したコンポーネントのエンコードは、クエリ値に適した区切り文字を含むすべての特殊文字をエンコードします。 encodeURI を使用した URL 全体のエンコードでは、完全な URL の構造文字が保持されます。フォームのエンコーディングは POST ボディ用です。それぞれ UTF-8 を使用します。それらは、どのバイトがエンコードされずに残されるかだけが異なります。

Punycode とフォーム エンコーディング: パーセント エンコーディング拡張ではなく、兄弟標準

バイト パースペクティブは URL の謎を解決します。なぜ 1 つの絵文字に 12 文字も必要なのでしょうか? UTF-8 は 4 バイトを使用し、それぞれが %HH になるためです。一部の URL ではスラッシュに %2F が使用されているのに、他の URL では単純なスラッシュが使用されているのはなぜですか?エンコード モードによって決定されるため、パス セグメント内のスラッシュはエンコードされませんが、クエリ値の内部では、誤読を避けるために %2F にする必要があります。

予測可能なパーセントエンコーディングについてはバイト単位で考えてください。文字は Unicode コード ポイントです。 UTF-8 はそのバイト表現です。パーセントエンコーディングは伝送形式です。文字の拡張は UTF-8 レイヤーで行われます。 16 進数の場合はデコードに影響しませんが、文字の場合は影響します。無効なバイト シーケンスは、厳密なプレフィックス ルールにより UTF-8 で失敗します。 URL エンコーダ ツールは、この進行を示します。

要点: バイト単位で考える — URL エンコーダーとデコーダーが、貼り付けたテキストの正確な %XX 出力をブラウザーにどのように表示するか

作業例: 「カフェ 😀」のエンコード。 「cafe」という単語には、ASCII シングルバイトの文字 c、a、f が含まれます: 63、61、66。 é は UTF-8 の 2 バイトです: C3 A9。スペースは 20 です。絵文字 😀 は 4 バイトです: F0 9F 98 80。予約されていない ASCII 文字は表示されたままになります。結果: 「caf%C3%A9%20%F0%9F%9880」。これは、1 つの絵文字が 12 文字に拡張される理由を示しています。

要点: 文字ではなくバイトで考えてください。パーセントエンコーディングは、UTF-8 エンコーディングの後に適用されます。各バイトは%HHになります。可変長 UTF-8 は、文字の拡張方法が異なることを意味します。ASCII は %XX (2 文字)、2 バイトのアクセントは %XX%XX (6 文字)、4 バイトの絵文字は %XX%XX%XX%XX (12 文字) になります。 URL エンコーダ ツールにテキストを貼り付け、進行状況を観察します。