用語辞典・データ・文字コード

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

パーセントエンコーディングとは

パーセントエンコーディング(percent-encoding/パーセント・エンコーディング)は、バイトを%の後ろの2桁16進数で表す符号化で、URLエンコードの中心となる方式です。ここでいうURLエンコードは成分ごとの変換処理を指します。

たとえば空白を表すバイト20%20と書けます。日本語などは先にUTF-8の複数バイトへ変わるため、一文字に複数の%HHが並びます。

%の後ろはUnicodeの符号位置ではなく、一個のバイト値です。文字→バイト列→%HH列という二段階を分けて読みます。

文字をバイト列へし、一バイトずつ%HHへする安全な文字・構造用の予約文字・変換対象を区別する
星形の文字が複数のバイト粒へ変わり、各粒がパーセント記号と二つの六角形からなる単位へ変換されURLの一部分へ収まる流れ、予約区切りと安全な文字、一回の復号、二重復号、不完全な表記、大小文字相当の同値を示すピクトグラム図解
図1図の六角形二個は16進数二桁を表します。正確な値は対象文字をどの文字エンコーディングでバイト化したかによって決まります。

%HHは一バイトの表記

Character文字列を受け取る

URL成分へ入れたい生の文字列を用意します。

Encodeバイト列へする

通常はUTF-8で一個以上のバイトへ変えます。

Hex一バイトを二桁へする

00〜FFの値を16進数二桁で表します。

Triplet%HHを作る

%を先頭に置いた三文字で一個のパーセントエンコード済みバイトになります。

そのまま使える非予約文字

ASCII英数字と-._~unreserved(アンリザーブド/非予約)文字です。通常はそのまま使え、パーセントエンコードしても表せますが、同じURLの文字列表現が増えるため、生成側は原則としてそのままにします。

%41Aのような表現を同じ資源と扱うかはURL処理で正規化される場合があります。キャッシュキー、署名、アクセス制御で文字列を直接比較するときは、どの正規形を使うかを決めます。

予約済み文字は文脈で意味が変わる

:/?#などはURL構造を作る予約文字です。区切りとしての/と、パスセグメント内のデータとしての%2Fは、サーバーやルーターの処理によって同じにならない場合があります。

先に復号してからパスを分割するのか、分割後に各セグメントを復号するのかで結果が変わります。プロキシ、framework、アプリケーションが同じ順序で処理するようにします。

16進数のA〜Fは大小文字どちらでもよい

%2f%2Fの16進数字は同じバイトを表します。生成時は大文字へ統一する実装が多いものの、受信側は両方を同じ値として扱います。

URLの別の部分まで大小文字を同一視できるわけではありません。ホストはASCII大小文字を区別しませんが、パスの大小文字を区別するかはサーバー側の仕組みによります。

不完全な表記は推測で補わない

%だけ、16進数が一桁だけ、16進数でない文字が続く表記は不正です。受信側がそのまま残すかエラーにするかはAPIで異なります。別解釈を勝手に作らず、期待する構文で検証します。

percent-decodeしたバイトが有効なUTF-8になるとも限りません。URL構文としての復号と、バイト列から文字列への復号は別段階で、それぞれエラー処理が必要です。

復号は一度だけ行う

%252eを一度復号すると%2e、二度復号すると.になります。検査層が一度だけ戻し、実行層がもう一度戻すと、隠れていた../、区切り、制御文字などが後から現れます。

外部入力をどの状態で受け取ったかを型や変数名で区別し、復号後にパスや問い合わせの制約を検証します。生のURL、解析済み成分、復号済み文字列を同じ変数で使い回しません。

パーセントエンコーディングは一バイトを%HHで表す規則です。先に文字をバイト化し、URL成分の文脈に必要なバイトだけを変換し、受信側では定めた段階で一度だけ戻します。

percent-encoded byteと成分別encode set:WHATWG URL Standard

関連用語