[9] [DFN[[CODE(MIME)[application/x-www-form-urlencoded]]]]
は、[[フォームの提出]]のための形式の1つです。 [[HTML]]
の[[フォームの提出]]のために開発され、 [[HTTP]] [CODE(HTTP)@en[[[POST]]]]
の [[payload body]] や [[HTTP]] [CODE(HTTP)@en[[[GET]]]] の
[[URL query]] で使われています。 [[HTML]] に限らず、
[[OAuth]] や各種サービスの [[Web API]] などでも標準的な入力形式として採用されています。

* 仕様書

[REFS[
- [68] '''[CITE@en-US[URL Standard]] ([TIME[2014-06-23 18:56:37 +09:00]] 版) <http://url.spec.whatwg.org/#application/x-www-form-urlencoded>'''
- [121] [CITE@en-GB-x-hixie[HTML Standard]] ([TIME[2015-01-30 08:05:01 +09:00]] 版) <https://html.spec.whatwg.org/#url-encoded-form-data>
]REFS]

[HISTORY[
[67] 歴史的には明確な仕様が存在せず、様々な仕様書がそれぞれの立場の規定を含めていました。
(歴史の項を参照。)
]HISTORY]

* データモデル

[39] [CODE(MIME)@en[[[application/x-www-form-urlencoded]]]] のデータは、
0個以上の[RUBYB[名前][name]]と[RUBYB[値]@en[value]]の組の列を表しています。

[42] 名前や値は、それぞれ0個以上の[[文字]]の列です。

;; [82] 仕様上は[[文字列]]になっていますが、[[バイト列]]が用いられることも稀にあるようです。

[43] 名前の重複は禁止されていません。名前と値の組の順序は意味を持ちます。

;; [51] [[応用]]によっては重複を禁じていたり、順序の意味を持たせなかったりすることもあります。

[74] 名前や値の[[値域]]や長さの制限はありません。大文字と小文字は区別されます。

;; [75] [[応用]]によっては制限を設けたり、区別しなかったりすることもあります。

* 構文

[11] [CODE(MIME)@en[[[application/x-www-form-urlencoded]]]] では、
名前と値の組を [CODE[[[&]]]] で区切って連結します。

[FIG(railroad)[
= ?
== 組
== *
=== [CODE[[[&]]]]
=== 組
]FIG]

[52] 名前と値は、 [CODE[[[=]]]] で連結します。

[FIG(railroad)[
= 名前
= [CODE[[[=]]]]
= 値
]FIG]

[72] 名前と値は、[[パーセント符号化]]することができます。
0x00-0x7F の範囲外や区切りの [CODE[[[&]]]] や [CODE[[[=]]]]
とみなされるもの、 [CODE[[[+]]]] は、[[パーセント符号化]]しなければなりません。

[73] 名前と値の [CODE[[[+]]]] は、 0x20 を表します。

* 文字コード

[77] [CODE(MIME)@en[[[application/x-www-form-urlencoded]]]] 自体は
[[ASCII]] によって表現されますが、その[[パーセント符号化]]を[[復号]]した結果は、
何らかの[[文字コード]]の[[文字列]]となっています。

;; [83] 仕様上は認められていませんが、[[文字列]]ではなく[[バイト列]]になっていたり、
複数の[[文字コード]]が混在したりすることも現実にはあるようです。

[107] [[[CODE(MIME)@en[application/x-www-form-urlencoded]]直列化器]]は、
特に指定がない限り [[UTF-8]] を使います [SRC[>>68]]。

;; [123] 歴史的な理由により、
[[HTML]] の[[フォームの提出]]では、 [CODE(HTMLa)@en[[[accept-charset]]]]
の指定や[[文書]]の[[文字符号化]]が使われます [SRC[>>121]]。
現在ではこうしたものは好ましくないと考えられており、 [CODE(HTMLa)@en[accept-charset]]
は指定するべきではなく、[[文書]]自体も常に [[UTF-8]] とするべきです。

;; [125] [[HTML]] では必ず[[ASCII互換文字符号化]]が選ばれます [SRC[>>121]]。

[170] [[[CODE(MIME)@en[application/x-www-form-urlencoded]]構文解析器]]は、
常に [[UTF-8]] を使って[[復号][UTF-8 decode without BOM]]します [SRC[>>68]]。

[HISTORY[

[78] [TIME[2017年1月][2017-01]]改訂以前の[[[CODE(MIME)@en[application/x-www-form-urlencoded]]構文解析器]]は、
次のように[[文字コード]]を決定していました [SRC[>>68]]。
[FIG(steps)[
= [79] [CODE[[[_charset_]]]] 有効で構文解析する場合には、
[CODE[[[_charset_]]]] という名前の組があり、
その値で[[符号化を取得]]して失敗しなければ、
得られた[[文字符号化]]
= [80] [[文字符号化]]の指定ありで構文解析する場合には、
その[[文字符号化]]
= [81] [[UTF-8]]
]FIG]

[129] かつての [CITE[HTML Standard]] が示していた[[復号]]アルゴリズムは、
[CODE[[[_charset_]]]] が含まれない場合[[文字コード]]はケースバイケースで決めるしかないとしつつも、
一般には[[フォーム]]が含まれる[[文書]]の[[文字コード]]を既定値とするのがよく、
適当な既定値がなければ [[UTF-8]] とするのがよさそうだ [SRC[>>121]] だとしています。
]HISTORY]

[133] [[HTML]] の[[フォーム]]では、 [CODE(HTML)@en[<input type=hidden name=_charset_>]]
という[[要素]]を含めることで、使用した[[文字コード]]を[[フォームデータ集合]]の一部として[[提出]]させることができます。

;; [[[CODE[_charset_]] hack]] を参照。

[HISTORY[
[84] 歴史的には [[_charset_ hack]] の他、 [CODE[[[ie]]]] のような名前の組で[[文字コード]]を指定したり、
固定の文字を指定した組を含めてその符号化された値により[[文字コード]]を推定したり、
自動判別を用いたり、[[フォーム]]が含まれる[[文書]]の[[文字コード]]と推定したりと色々な方法が用いられてきました。
しかし現在では専ら [[UTF-8]] が使われているとみなすことが多くなってきています。
]HISTORY]

[124] なお、選択した[[文字コード]]で表現できない文字を [[URL Standard]]
や [[HTML Standard]] の[[アルゴリズム]]は[[十進数文字参照]]によって表現します
[SRC[>>68, >>121]]。[[十進数文字参照]]は [CODE[[[&]]]] から始まりますが、
後から[[パーセント符号化]]されるので区切り文字と誤認されることはありません。
しかしただの [CODE[[[&]]]] はそのまま送信されるので、元のデータが [CODE[&]]
だったのか[[符号化]]によって[[十進数文字参照]]となったのかは区別できません。

;; この点からも、すべての[[文字]]をそのまま表現できる [[UTF-8]] を使うべきです。

* パーセント符号化

[85] 名前と値は[[パーセント符号化]]することになっています。

[86] [[[CODE(MIME)@en[application/x-www-form-urlencoded]]直列化器]]は、
[DFN[[RUBYB[[[[CODE(MIME)@en[application/x-www-form-urlencoded]]バイト直列化器]]]@en[[CODE(MIME)@en[application/x-www-form-urlencoded]] byte serializer]]]]によって[[パーセント符号化]]します。具体的には、次の[[バイト]]はそのままとし、
0x20 は [CODE[[[+]]]] とし、
それ以外は[[パーセント符号化]]します。 [[HTML]] の[[フォーム]]でも同様です。 [SRC[>>68, >>121]]
[FIG(list short)[
- 0x2A (*)
- 0x2D (-)
- 0x2E (.)
- 0x30-0x39 (0-9)
- 0x41-0x5A (A-Z)
- 0x5F (_)
- 0x61-0x7A (a-z)
]FIG]

;; [87] これらは[[バイト]]であり、[[文字]]ではありません。ですから、例えば
[CODE[[[+]]]] は 0x20 を表しており、 [CODE(char)[[[U+0020]]]] を表すとは限りません。

;; [88] [[URL]] の[[非予約文字]]である[[ASCII文字]]のうち、
[CODE[[[~]]]] は[[パーセント符号化]]されます。

[REFS[
- [154] [CITE@en[Character set "ASCII character of byte percent-encoded by application/x-www-form-urlencoded byte serializer"]] ([TIME[2016-04-27 17:28:11 +09:00]] 版) <https://chars.suikawiki.org/set/%24url%3Aform%3Apercent-encoded-byte-char>
- [155] [CITE@en[Character set "ASCII character of byte represented as "+" by application/x-www-form-urlencoded byte serializer"]] ([TIME[2016-04-27 17:28:31 +09:00]] 版) <https://chars.suikawiki.org/set/%24url%3Aform%3Aplus-byte-char>
- [156] [CITE@en[Character set "ASCII character of byte not encoded by application/x-www-form-urlencoded byte serializer"]] ([TIME[2016-04-27 17:28:46 +09:00]] 版) <https://chars.suikawiki.org/set/%24url%3Aform%3Aunencoded-byte-char>
]REFS]

[90] [[URL Standard]] は [[[CODE(MIME)@en[application/x-www-form-urlencoded]]直列化器]]によって生成される
[CODE(MIME)@en[[[application/x-www-form-urlencoded]]]] においてこのように[[パーセント符号化]]することを求めていますが、
その他の方法で [CODE(MIME)@en[[[application/x-www-form-urlencoded]]]]
が生成されることは排除していないようです。例えば [[Web]]
以外の[[利用者エージェント]]が [CODE(MIME)@en[[[application/x-www-form-urlencoded]]]]
を使うときに他の[[文字]]を[[パーセント符号化]]したり、しなかったりしてもただちに問題とはなりません。

[92] ただし [[[CODE(MIME)@en[application/x-www-form-urlencoded]]構文解析器]]は
[[UTF-8]] 以外の[[文字コード]]の時に 0x80-0xFF が入力に含まれていると、
[[構文解析]]せずに停止することになっています [SRC[>>68]]。
[[相互運用性]]のために最低でも 0x80-0xFF は[[パーセント符号化]]するべきでしょう。

[108] [[HTML4]] のあまり意味がなかった規定 (>>13) の影響で区切り文字として
[CODE[[[;]]]] をも認識する[[鯖]]側の実装が少なくありませんから、
0x3B ([CODE[[[;]]]]) も[[パーセント符号化]]するべきでしょう。

[164] [CODE(URI)@en[encodeURIComponent]] など汎用的な[[パーセント符号化]]の実装を使っていると、
より多くの[[文字]]が[[パーセント符号化]]されます。

[165] 特にこだわりがなければ、 [[Webブラウザー]]に合わせる (>>86) か、
より保守的な方式を採用する (>>164) のが良さそうです。

[145] 歴史的に [[Webブラウザー]]やその他の[[クライアント]]がどの[[文字]]・[[バイト]]を[[パーセント符号化]]し、
どれをそのまま残すかには微妙な違いがあります。しかし仕様通りの方法で[[復号]]していれば、
その違いも自然に吸収されます。



[91] [[[CODE(MIME)@en[application/x-www-form-urlencoded]]直列化器]]や
[[HTML]] [[フォーム]]による[[パーセント符号化]]では、[[大文字]]の[[十六進数字]]を使います [SRC[>>68, >>121]]。

[166] [[Webブラウザー]]以外の多くの実装も、[[大文字]]を使うのが普通のようです。

[97] [[[CODE(MIME)@en[application/x-www-form-urlencoded]]構文解析器]]は、
[[パーセント符号化]]が[[大文字]]でも[[小文字]]でも[[復号]]します [SRC[>>68]]。

* [CODE[+]]

[89] 0x20 を [CODE[[[+]]]] で表すのは 
[CODE(MIME)@en[[[application/x-www-form-urlencoded]]]]
独特の方式 ([DFN[[RUBYB[プラスパーセント符号化]@en[plus-percent-encoding]]]]) で、
通常の[[パーセント符号化]]では行われていません。

[58] 通常の[[パーセント符号化]]を流用した実装では、 0x20 が [CODE[[[+]]]]
ではなく [CODE[%20]] と表現されているかもしれません。

[EG[
[143] [[Webブラウザー]]が[[フォームの提出]]を行う時は [CODE[[[+]]]]
を使いますが、[[スクリプト]]が [[URL]] を組み立てる時は 
[CODE(JS)@en[[[encodeURIComponent]]]] を使って [CODE[[[U+0020]]]] を
[CODE[[[%20]]]] と[[符号化]]しているかもしれません。
]EG]

;; [144] [[Webブラウザー]]が従うべき [CODE(MIME)@en[[[application/x-www-form-urlencoded]]]]
の[[符号化]]のアルゴリズム上は [CODE[[[+]]]] を使うことになっていますが、
[CODE(MIME)@en[[[application/x-www-form-urlencoded]]]] という構文としては
[CODE[[[%20]]]] の利用が禁止されているわけではありません。

;; [160] [[パーセント符号化]]の [CODE[+]] の章も参照。

[HISTORY[
[161] 通常の[[パーセント符号化]]と違って [CODE[+]] を使うのは、
かつての [CODE(HTMLe)@en[isindex]] の送信方法 (>>127) に由来すると思われます。
[CODE(HTMLe)@en[isindex]] では[[空白]]区切りで複数の[[キーワード]]を指定して検索するという意味で、
[[パーセント符号化]]された[[キーワード]]を [CODE[+]] で連結して [[query][URL query]]
に指定する方法を採っていました。

[162] [[CGIサーバー]]は、 [[query][URL query]] に [CODE[=]] が含まれないなら、
[CODE[+]] 区切りの[[パーセント符号化]]された[[キーワード]]列として解釈し、
各[[キーワード]]を [[CGIスクリプト]]の[[コマンドライン引数]]として使います。

;; [[スクリプトコマンドライン]]参照。

[163] [[フォームの提出]]でこの方法を踏襲しなければならない理由も無いのですが、
[[フォーム]]を最初に実装した [[Mosaic]] の時点で [CODE(HTMLe)@en[isindex]]
は内部的に[[フォーム]]に置き換えられていたようですから、
同じ[[符号化]]方法を採用した方が都合が良かったのでしょう。
]HISTORY]

* [CODE[=]] のない組

[98] [[[CODE(MIME)@en[application/x-www-form-urlencoded]]直列化器]]は 
[CODE[[[=]]]] が含まれない名前と値の組を生成することはありませんが、
実際には含まれないこともあるので、
[[[CODE(MIME)@en[application/x-www-form-urlencoded]]構文解析器]]は処理方法を規定しています。

[99] それによると、原則としてその部分全体を名前として扱い、値は[[空文字列]]とします
[SRC[>>68, >>121]]。

[HISTORY[
[127] かつては [CODE(HTMLe)@en[isindex]] [[要素]]との互換性のための規定がありましたが、
2016年4月の [CODE(HTMLe)@en[isindex]] [[要素]]の完全[[廃止]]により、削除されました。

[100] ただし [CODE[[[isindex]]]] 対応で構文解析する場合であって、
最初の名前と値の組の部分に [CODE[[[=]]]] が含まれない場合に限り、
名前は[[空文字列]]とし、その部分全体を値として扱います [SRC[>>68, >>121]]。

;; [101] しかし [[[CODE(MIME)@en[application/x-www-form-urlencoded]]構文解析器]]を使って解釈される保証はありませんし、
[CODE[[[isindex]]]] 対応で構文解析されるかどうかもわかりませんから、
[CODE[[[=]]]] は必ず含めるべきでしょう。

[126] [[HTML]] の[[フォーム]]から生成する際、[[フォームデータ集合]]の最初の項目の名前が
[CODE(HTML)@en[[[isindex]]]] で種別が [CODE(HTML)@en[[[text]]]] なら、
値を[[パーセント符号化]]したもののみを結果に含め、名前や [CODE[[[=]]]]
は省略します [SRC[>>121]]。
]HISTORY]

* MIME 型の引数

[93] [CODE(HTTP)@en[[[Content-Type:]]]] に [CODE(MIME)@en[[[application/x-www-form-urlencoded]]]]
が指定される際に、[[引数]]も指定されることがあります。

[94] かつては[[引数]]に対応していない実装も少なくありませんでしたが、
その後 [CODE(MIME)@en[[[charset]]]] [[引数]]を指定する実装が出てきたことから、
現在では[[引数]]に対応 (無視) しないと[[Web互換]]とは言えない状況にあります。

[95] [[URL Standard]] や [[HTML Standard]] は [CODE(MIME)@en[[[charset]]]]
[[引数]]を規定しておらず、解釈の際にも用いないことになっています。
[[HTML Standard]] には無視すると明記されています [SRC[>>121]]。
しかしかつて標準不在だった時代に[[文字コード]]を明記するために
[CODE(MIME)@en[[[charset]]]] [[引数]]を使った実装や、
意味もなく見よう見まねで [CODE(MIME)@cn[[[charset]]]] [[引数]]を使った実装や使用例もありました。
現在でもその名残りでしばしば [CODE(MIME)@en[[[charset]]]] [[引数]]を見かけます。

[96] [CODE(MIME)@en[[[charset]]]] [[引数]]は指定するべきではありません。
指定されていても、無視するべきです。中には指定されていたらそれに従う実装もあるかもしれませんが、
無視する実装が普通なので、[[相互運用性]]の問題に陥るおそれもあります。

* 文脈

[49] [CODE(MIME)@en[[[application/x-www-form-urlencoded]]]] は、 
[[HTML]] その他の[[フォーム]]の[[提出]]や、 [[Web API]] その他の[[引数]]の指定などのため、
[[HTTP]] [[payload body]] や [[HTTP要求]]の[[要求URL]] の [[URL query]]
として非常によく使われています。

[50] [CODE(MIME)@en[[[application/x-www-form-urlencoded]]]] は、
[[OAuth 1.0]] で[[鯖]]から[[クライアント]]への[[HTTP応答]]の [[payload body]]
で使われています。実装によっては [[OAuth 2.0]] でも使われています。

[137] [CODE(MIME)@en[[[application/x-www-form-urlencoded]]]] は、
[[OAuth 2.0]] で[[素片識別子]]で使われています。

;; [[認可エンドポイント]]を参照。

[140] [[OAuth 2.0]] [[クライアント認証]]における[[基本認証]]では
[CODE(MIME)@en[[[application/x-www-form-urlencoded]]]]
の[[パーセント符号化]]が採用されています。

* 演算

[105] [[URL Standard]] は、 [DFN[[RUBYB[[CODE(MIME)@en[application/x-www-form-urlencoded]]直列化器]@en[[CODE(MIME)@en[application/x-www-form-urlencoded]] serializer]]]]を規定しています
[SRC[>>68]]。この[[アルゴリズム]]は、名前 (文字列) と値 (文字列)
の組の列を入力とし、[[バイト列]]を出力とします。また[[文字符号化]]をオプション入力として持ちます。

;; [106] 本項の他の部分で説明している通り、
[CODE(MIME)@en[[[application/x-www-form-urlencoded]]]] の一般的な構文を示すものとなっています。
しかし [CODE(MIME)@en[[[application/x-www-form-urlencoded]]]] をこの方法で生成しなければならないとは規定されておらず、
実際これに従わない [CODE(MIME)@en[[[application/x-www-form-urlencoded]]]]
のデータも存在します。 [CODE(MIME)@en[[[application/x-www-form-urlencoded]]]]
のデータの適合性の規定は存在していないので、そのようなデータに問題があるとはいえません。
しかし[[相互運用性]]のためには、 [[Webブラウザー]]が実装している
[[[CODE(MIME)@en[application/x-www-form-urlencoded]]直列化器]]の動作に倣うべきでしょう。

[158] [CODE(URI)@en[mailto:]] [[URL]] への[[フォームの提出]]では、
[[[CODE(MIME)@en[application/x-www-form-urlencoded]]直列化器]]の出力の
[CODE[+]] を [CODE[%20]] に置換する場合があります。
つまり通常の[[パーセント符号化]]相当の動作とするべきことになります。

[102] [[URL Standard]] は、 [CODE(MIME)@en[[[application/x-www-form-urlencoded]]]]
を解釈する方法として[DFN[[RUBYB[[CODE(MIME)@en[application/x-www-form-urlencoded]]構文解析器]@en[[CODE(MIME)@en[application/x-www-form-urlencoded]] parser]]]]を規定しています
[SRC[>>68]]。この[[アルゴリズム]]は、[[バイト列]]を入力とし、
名前 (文字列) と値 (文字列) の組の列または失敗を出力とします。また、
[[文字符号化]]、[CODE[[[_charset_]]]] を使うか否か[DEL[、 [CODE[[[isindex]]]] を使うか否か]]をオプション入力として持ちます。

;; [103] 本項の他の部分で説明している通り、
[CODE(MIME)@en[[[application/x-www-form-urlencoded]]]] の汎用的な構文解析の方法を示すものとなっています。

[104] [[URL Standard]] は、 [DFN[[RUBYB[[CODE(MIME)@en[application/x-www-form-urlencoded]]文字列構文解析器]@en[[CODE(MIME)@en[application/x-www-form-urlencoded]] string parser]]]]も規定しています
[SRC[>>68]]。この[[アルゴリズム]]は、[[文字列]]を入力とし、
名前 (文字列) と値 (文字列) の組の列を出力とします
(失敗はしません)。これは入力を [[UTF-8符号化]]してから
[DFN[[CODE(MIME)@en[application/x-www-form-urlencoded]]構文解析器]]を呼び出す
[SRC[>>68]] というものになっています。

;; [CODE(DOMi)@en[[[URLSearchParams]]]] 関連 [[API]] で使われています。

[HISTORY[
[153] かつては [[HTML Standard]] にも独自の規定がありましたが (歴史的にはこちらが先)、
[[URL Standard]] の規定に一本化されました。

[122] [[HTML Standard]] は、
[DFN[[RUBYB[[CODE(MIME)@en[application/x-www-form-urlencoded]]符号化アルゴリズム]@en[[CODE(MIME)@en[application/x-www-form-urlencoded]] encoding algorithm]]]]として[[フォームデータ集合]]から生成する方法を規定しています [SRC[>>121]]。
[CODE(HTML)@en[[[isindex]]]] への対応を除けば [[URL Standard]] のアルゴリズムとほぼ同じですが、
[[HTML]] の[[フォーム]]に特化した形で規定されています。
入力は[[フォーム]]と[[フォームデータ集合]]で、出力は[[バイト列]]です。

[128] [[HTML Standard]] は、 [DFN[[RUBYB[[CODE(MIME)@en[application/x-www-form-urlencoded]] payloadの復号]@en[decode [CODE(MIME)@en[application/x-www-form-urlencoded]] payloads]]]]の方法も規定しています [SRC[>>121]]。
この[[アルゴリズム]]は [[U+0000]]-[[U+007F]] の範囲の[[文字列]]および[[文字符号化]]と
[CODE(HTML)@en[[[isindex]]]] 対応の有無を入力とし、
名前 (文字列) と値 (文字列) の組の[[整列]]リストを出力とします [SRC[>>121]]。
この[[アルゴリズム]]は、入出力のデータ型を除けば[RUBYB[[CODE(MIME)@en[application/x-www-form-urlencoded]]構文解析器]@en[[CODE(MIME)@en[application/x-www-form-urlencoded]] parser]]と同じです。
]HISTORY]

* フォーム・データ集合からの生成

@@ 本項は古くなっています。

[18] HTML 4 は、 [CODE(MIME)[application/x-www-form-urlencoded]]
のデータは[[フォーム・データ集合]]から次のように生成しなければならないと規定しています
[SRC[HTML 4 17.13.4.1]]。

= 制御子の名前と値を escape します。
== 間隔は [CODE(URI)[+]] に置換します。
== 予約文字は [[RFC 1738]] 2.2 節の規定の通り escape します。
== 改行は [CODE(URI)[%0D%0A]] で表現します。
= 制御子の名前・値は[[文書順]]で並べます。
名前と値は [CODE(URI)[=]] で分離し、
名前・値の組は相互に [CODE(URI)[&]] で分離します。

[21] XForms 1.0 は、 [CODE(MIME)[application/x-www-form-urlencoded]]
による[[直列化]]を次の通り規定しています [SRC[XForms 1.0 11.6]]。

= 各[[要素節]]を[[文書順]]に見ていきます。
1つ[[文節]]を含む要素節を選びます。
= 要素節毎に、 [SAMP(URI)[[VAR[EltName]]=[VAR[value]][VAR[{sep}]]]]
という文字列を作ります。
-- [VAR[EltName]] は要素節の[[局所名]]です。
=== 間隔は [CODE(URI)[+]] で置換します。
=== 非 ASCII 文字および予約文字 ([[RFC 2396]] およびその改訂によります。)
を UTF-8 で URI escape します。16進数は大文字で表現します。
=== 改行は [CODE(URI)[%0D%0A]] とします。
-- [VAR[value]] は文節の内容です。
-- [VAR[{sep}]] は [CODE(XMLe)[[[submission]]]] の [CODE(XMLa)[[[separator]]]]
属性で指定された分離子文字です。
-- なお、要素節の属性や名前空間など他の情報は使われません。
= すべてを文書順に連結します。

[20] HTML では、フォーム制御子ごとにフォーム・データ集合に何が含まれるのかが異なります。
[[フォーム・データ集合]], [[成功]], [[現在値]]の説明をごらんください。
特に、ファイル選択制御子 ([[[CODE(HTMLe)[input]]/[CODE(HTML)[file]]]])
の現在値はファイル名の並びであり、ファイルの内容ではありません。
また、画像提出ボタン制御子 ([[[CODE(HTMLe)[input]]/[CODE(HTML)[image]]]])
では座標が含まれます。

[[HTML 2.0]] では、[Q[値無し (null) な欄は省略しても構わない]<urn:ietf:rfc:1866>]
などの規定が含まれていましたが、 HTML 4 
では整理されて[[成功]]制御子の選択に関する規定に移動しています。

* 名前

[41] [CODE(MIME)@en[[[application/x-www-form-urlencoded]]]] としては名前と値の組で特別な意味を持つのは
[CODE(URI)@en[[[_charset_]]]] だけですが、文脈次第で更にいくつかの名前が特別な意味を持つこともあります。

[44] [CODE(URI)@en[[[_charset_]]]] は、 [[_charset_ hack]] により[[文字コード]]を指定するために使われます。

[45] [[OAuth 1.0]] においては、 [CODE(URI)@en[[[oauth_]]]] から始まる名前は [[OAuth 1.0]]
用に予約されており、[[応用]]が勝手に使ってはなりません。

[142] [[OpenID 2.0]] は [CODE(URI)@en[[[openid.]]]] から始まる名前を [[OpenID]]
の用途で使っていました。

[141] [[OAuth 2.0]] はいくつかの[[引数]]名を規定しています。

;; [[OAuth 2.0]] 参照。

[47] [[媒体素片]]を [[URI query]] として使う場合には [CODE(URI)@en[[[t]]]]
などいくつかの名前が[[媒体素片]]仕様の規定に従って解釈されるべきものとなります。

[48] [[フォームの提出]]では [CODE(URI)[[[.x]]]] や [CODE(URI)[[[.y]]]] で終わる名前や
[CODE(URI)[[[x]]]] や [CODE(URI)[[[y]]]] は特別な用法を持っています。

[HISTORY[
[46] かつて[[フォームの提出]]では [CODE(URI)@en[[[isindex]]]] という名前が特別な意味を持ち、
通常の方法で使うことはできませんでした。
]HISTORY]

* 転送符号化との関係

[36] あまり見かけませんが、[[電子メイル]]でフォームを提出することもありますから、
[CODE(MIME)[application/x-www-form-urlencoded]] が [[MIME]]
で使われることもあります。

MIME の [CODE(MIME)[[[Content-Transfer-Encoding]]]] は、普通は不要です
([CODE(MIME)[[[7bit]]]] で十分です)。
[WEAK[([CODE(MIME)[application/x-www-form-urlencoded]] 自体が転送符号化のようなものですから。)]]
ただし、少しでもデータ量が多いと改行がない
[WEAK[(あったとしても[[百分率符号化]]されている)]]
ので、電子メイル / MIME の行長制限に引っかかることが容易に考えられます。
その場合は CTE が必要になります。

CTE は [CODE(MIME)[[[Quoted-Printable]]]] が適当です。
元々7ビットのデータなのですから [CODE(MIME)[[[Base64]]]]
は効率が悪すぎます。

* 歴史

** 誕生

[109] [CODE(MIME)[[[application/x-www-form-urlencoded]]]] は [[HTML2]]
で[[フォーム]]が導入された時に、その(唯一の)表現方法として規定されました。

;; [CODE(HTMLa)@en[[[enctype]]]] も参照。

[REFS[
- [[RFC 1866]] - [[HTML 2.0]]
- [[RFC 2070]] - [[HTML 2.x]]
]REFS]

** HTML4

[111] [[HTML4]] は[[フォームデータ集合]]を [CODE(MIME)@en[[[application/x-www-form-urlencoded]]]]
で[[符号化]]する方法 [SRC[>>110]] を規定していました。

[REFS[
- [110] [CITE@en[Forms in HTML documents]] ([TIME[1999-12-25 08:25:52 +09:00]] 版) <http://www.w3.org/TR/html4/interact/forms.html#h-17.13.4.1>
- [119] [CITE@en[Performance, Implementation, and Design Notes]] ([TIME[1999-12-25 08:26:00 +09:00]] 版) <http://www.w3.org/TR/html4/appendix/notes.html#ampersands-in-uris>
]REFS]

[19] [[HTML4]] は[[改行]]を [CODE[%0D%0A]] と表現するとの規定を持っていました [SRC[>>110]] 
が、 [[HTML5]] では[[改行]]の正規化は [CODE(MIME)@en[[[application/x-www-form-urlencoded]]]]
ではなく[[フォームデータ集合]]の過程となっています。

;; [112] [[OAuth 1.0]] は [[HTML4]] を参照しており、厳密に解釈すると [[OAuth]]
にもこれが適用されることになりますが、一般的にはそうは解釈されていないように思われます。

[138] [[ASCII文字]]のどれを[[パーセント符号化]]しなければならず、
どれを[[パーセント符号化]]してはならないかについて、 [[HTML4]]
は明確に規定していませんでした。

[113] [[パーセント符号化]]を大文字にするか小文字にするかについて、 [[HTML4]]
は言及していませんでした。

[114] [[HTML4]] は[[ASCII]]以外に [CODE(MIME)@en[[[application/x-www-form-urlencoded]]]]
は不適切で、 [CODE(MIME)@en[[[multipart/form-data]]]] を使うべきである [SRC[>>110]] とし、
[[非ASCII文字]]が [CODE(MIME)@en[[[application/x-www-form-urlencoded]]]]
でどう表現されるべきかに一切言及していませんでした。

[115] 当時の時代的限界とはいえ、実際に既に広く使われていた[[非ASCII文字]]の[[フォーム]]と
[[Webブラウザー]]の存在 (と世界の大多数の[[非ASCII文字]]利用者の存在) 
を無視して規定を怠ったため、[[文字コード]]の解釈に関する混乱はその後も数年継続することとなってしまいました。

;; [116] [[[CODE[_charset_]] hack]] は当時まだありませんでした。
[CODE(MIME)@en[[[charset]]]] [[引数]]もまだ見られませんでした。

;; [117] [CODE(MIME)@en[[[multipart/form-data]]]] は [CODE(HTTP)@en[[[GET]]]]
では使えませんし、 [CODE(HTTP)@en[[[POST]]]] でもサイズが増えることが多いですし
([[HTML4]] は[[非ASCII文字]]に [CODE(MIME)@en[[[application/x-www-form-urlencoded]]]]
は非効率的と言っており、それは正しいですが、[[フォームデータ]]のように短いデータの場合は
[CODE(MIME)@en[[[multipart/form-data]]]] の方がずっと大きくなります。)、
[CODE(MIME)@en[[[multipart/form-data]]]] の構文解析は数倍面倒になりますから、
(一応は現に動作している) [CODE(MIME)@en[[[application/x-www-form-urlencoded]]]]
から移行する動機はほとんど無く、 [[HTML4]] のこの記述は現実には無視されていました。

;; [118] 理論上は [CODE(MIME)@en[[[multipart/form-data]]]] は [CODE(MIME)@en[[[charset]]]]
により[[文字コード]]を明記できますが、実際には現在に至るまで [[Webブラウザー]]は
[CODE(MIME)@en[[[charset]]]] [[引数]]を使っていないので、実は
[CODE(MIME)@en[[[multipart/form-data]]]] にすれば[[文字コード]]の問題が解決するわけではありません。

[13] 名前と値の組の区切りは [CODE[[[&]]]] ですが、 [[HTML4]]
は [[URL query]] に [CODE[[[&]]]] が含まれると[[属性値]]として指定するときに[[escape]]
が必要になるため、かわりに [CODE[[[;]]]] も認めるべき [SRC[>>119]]
としており、 [CODE(MIME)@en[[[application/x-www-form-urlencoded]]]]
の実装がそのような配慮を行うことを暗に求めています [SRC[>>110]]。

[14] [[HTML4]] はあまり明確に説明していませんが、行間によると、
[[鯖]]は[[フォームの提出]] (特に [CODE(HTTP)@en[[[GET]]]] の場合) と [[URL query]]
をしばしば同一のコードにより処理されるため、 [[URL query]] で [CODE[[[;]]]]
を区切りとして用いることを促進するべくそのような説明になっていると思われます。

[33] これに従い [CODE(MIME)@en[[[application/x-www-form-urlencoded]]]]
でも [CODE[[[;]]]] を区切りとみなす実装が多々あります。

[120] しかし [CODE(HTTP)@en[[[GET]]]] で[[フォームの提出]]を行うと
[CODE[[[&]]]] を生成する [[Webブラウザー]]の動作は変更するわけにはいかず、
その [[URL]] をコピペして[[リンク]]の [[URL]] に使うのも一般的なので、
[[HTML4]] が狙っていた [CODE[[[;]]]] への移行ははじめから無理な話でした。

** 

[10] 独立して [CODE(MIME)[application/x-www-form-urlencoded]]
を規定する仕様書は長らく存在しませんでした。 HTML や [[XForms]]
など、採用する規格の仕様書が個々に定義しています。
なお、定義しようという Internet-Draft がでているので後述。

- [[XForms 1.0]] ☆
-- [CITE[11.6 Serialization as application/x-www-form-urlencoded]]
<IW:XForms:"xforms/slice11.html#serialize-urlencode">
- [[WML]]
-- 
<http://www.openmobilealliance.org/wapdocs/wap-191_105-wml-20020212-a.pdf>
-- [CITE[WAP 日本仕様ガイドライン (日本語を用いたコンテンツ作成環境) — WAP June 2000 Conformance Release 対応版 —]],
2000 年10 月25 日 1.0 版, モバイル・インターネット・アクセス・フォーラム
第1技術部会 SPEC 作業班。
- [[WSDL]]
-- [CITE[Web Services Description Language (WSDL) Version 2.0 Part 3: Bindings 3.8.1 Serialization as "application/x-www-form-urlencoded"]]
<http://www.w3.org/TR/wsdl20-bindings/#_http_x-www-form-urlencoded>
- [[TAG Finding]]:
[CITE[URIs, Addressability, and the use of HTTP GET and POST 5.1 Internationalization]] 
<http://www.w3.org/2001/tag/doc/whenToUseGet.html#i18n>
- [CITE[J‐スカイサービス向け HTML コンテンツ開発ガイド 2.4.2.2. 携帯端末⇒ウェブサーバ]]
- [CITE[ボーダフォンライブ!向けウェブコンテンツ開発ガイド [HTML 編] 2.4.2.2. 端末⇒Web サーバ]]
- [[RFC 3875]] ([[CGI/1.1]])
-- [CODE[4.1.7 QUERY_STRING]]
-The application/www-form-urlencoded format draft-hoehrmann-urlencoded-01 <http://tools.ietf.org/html/draft-hoehrmann-urlencoded-01>
- [[RFC 5849]] ([[OAuth 1.0]]) <http://tools.ietf.org/html/rfc5849>

[SAMP[☆]]を付けたのは、特に重要な規定を含むものです。
その他は、補助的な規定や他の仕様を参照するものなどのうち、
特に多く章を裂いているものを挙げています。この他単に
[CODE(MIME)[[[application/x-www-form-urlencoded]]]] 
を参照しているだけの仕様は枚挙に暇がありません。

[53]
[CITE@en[Web Services Description Language (WSDL) Version 2.0 Part 2: Adjuncts]] ([CODE[2007-06-23 05:33:39 +09:00]] 版) <http://www.w3.org/TR/2007/REC-wsdl20-adjuncts-20070626/#_http_x-www-form-urlencoded>

[76] 文字の符号化の方法 ([[charset]]) は規定されていません。
HTML 4 は [[ASCII]] 文字だけが使用できると述べています
[SRC[HTML 4 17.13.1 Note]] が、現実には任意の符号化方式が使われています。
(ASCII 非互換なものも含まれます。) URI 符号化を使うことからも明らかなように、
任意のバイナリ・データの転送に使用するのには向いていませんが、
稀にそのような用途でも使われます。 (但し、そのような場合であっても、
フォームの他の文字的データと共に転送する目的であり、
専らバイナリ・データを転送するために使用することは考えにくいです。)
XForms はバイナリ内容には他の直列化方式を使うことを推奨しています
[SRC[XForms 1.0 11.6]]。

[12] [CODE(MIME)[application/x-www-form-urlencoded]]
の書式を [[ABNF]] で表現してみたのが次の生成規則です。
但し、すべての仕様・実装がこの規則に合致しているわけではありません。

= body = field *(separator field) / obs-body
= separator = "&" / obs-separator
= field = name "=" value
= name = 1*uchar / obs-name
= value = 1*uchar / obs-value
= uchar = ALPHA / DIGIT / "-" / "_" / "." / "," / ":" / joint / escaped / obs-uchar
= joint = "+"
= escaped = "%" escaped-code / "%0D%0A"
= escaped-code = "0" ( "0" / .. / "9" / "B" / "C" / "E" / "F" ) / ( "1" / .. / "7" ) HEXDIGIT / obs-escaped-code
= obs-escaped-code = 2HEXDIGIT
= obs-separator = ";"
= obs-body = *(separator field) [ separator ]
= obs-name = *uchar
= obs-value = *uchar
= obs-uchar = "'" / "(" / ")" / ";" / "$" / "@" / "*" / "!"

[15] HTML フォームの提出に際して [[UA]] が使用する charset
は、 >>14 の通り、 HTML 4 は規定していません。
実装は、
- 文書の charset と同じものを使用する
- UA の charset (UA の内部符号やその環境の符号) と同じものを使用する
- [CODE(HTMLa)[[[accept-charset]]]] で指定されたものを使用する

の3種類と、その混合があります。利用者によって編集されていないフォーム欄
(例えば [[[CODE(HTMLe)[input]]//[CODE(HTML)[hidden]]]] による隠し制御子)
は文書の charset で、編集された欄は UA の charset
で符号化するという UA すらかつて存在しました。 (その名も
[[WinIE 3]]。)

[[XForms]] は、 [[UTF-8]] を使用すると規定しています [SRC[XForms 1.0 11.6]]。

*** 百分率符号化

[37] [[文字]] (あるいは[[オクテット]]) を[[百分率符号化]]するかどうかについて、
各仕様は次のように規定しています。

:[[HTML 4]]:[[間隔]]は [CODE(URI)[+]] とします。
それ以外の非[[英数字]]は [[RFC 1738]] 2.2節の方法で符号化
(百分率符号化) します。 RFC 1738 によると、
百分率符号化には大文字の[[十六進数字]]を使いますが、
小文字を使っても構いません。[[改行]]は
[CODE(URI)[%0D%0A]] とします。
:[[XForms 1.0]]:[[間隔]]は [CODE(URI)[+]] とします。
非 ASCII 文字と、 [[RFC 2396]]
(または以後の改訂) の[[予約]]文字は百分率符号化します。
百分率符号化には大文字の十六進数字を使います。
改行は [CODE(URI)[%0D%0A]] とします。

[38]
XForms 1.0は RFC 2396 の予約文字を符号化しろとは言っていますが、
[[非安全]]文字 ([[URI参照]]で使えない文字) を符号化しろとは言っていません。
これはミスではないですかね?

しかも URI の規格の最新版自動追尾になっております。
従って、どの URI の規格に従うかによって現時点で
3種類の方法があり得ます。

:RFC 2396 による予約文字:[CODE(regex)['''[''';/?:@&=+$,''']''']]
:[[RFC 2732]] による予約文字:[CODE(regex)['''[''';/?[]:@&=+$,''']''']]
:[[RFC 3986]] による予約文字:[CODE(regex)['''[''':/?#[]@!$&'()*+,;=''']''']]

** URI 符号化

[16] 名前と値は、適当な charset によるオクテット表現を URI escape 符号化します。
XForms 1.0 [SRC[XForms 1.0 11.6]]
によれば、

- [[間隔]]文字は、 [CODE(URI)[+]] とします。
- [[改行]]は、 [CODE(URI)[%0D%0A]] とします。
- その他の URI 予約文字 ([CODE(ABNF)[[[reserved]]]])
および非 ASCII 文字 (オクテット) は、 [CODE(URI)[%[VAR[HH]]]]
とします。

16進数表現 [VAR[HH]] は、 XForms によれば大文字を使います。

[17] この URI escape 符号化は名前にも値にも適用されますが、
[[制御子名]]に非 ASCII 文字や URI 予約文字を使うことはあまりないので、
名前の URI escape 符号化を復号しないフォーム処理エージェントが少なくないと推測されます。

** Charset の識別

[22] >>11, >>14- にあるように、 [CODE(MIME)[application/x-www-form-urlencoded]]
では、文字の符号化の方法が定まっていません。ですから、
判定のためにいくつもの方法が使われています。

:決め打ち:特定の charset で提出されることが見込める環境のフォーム処理エージェントは、
charset に関する判定・変換を行いません。例えば、欧米で利用されており、
[[ASCII]] または [CODE(charset)[[[ISO-8859-1]]]] 
などで提出する利用者ばかりであると見込めるなら、
受け取ったデータをそのまま内部で使用していることがよくあります。
また、[[iモード]]などの特定の機器から利用することを想定しているフォーム処理エージェントは、
[[シフトJIS]] (iモード拡張版) でデータを受け取るものと想定していることがよくあります。
:自動判別:複数の charset が混在することが普通な環境では、
古くから自動判別によって内部用の charset に変換するなどしてから処理に使用するようにフォーム処理エージェントが設計されています。
例えば、日本語圏では昔から3つの符号化方式が混在してきましたから、
そのいずれであるかを判定し、どれかに統一するのが普通になっています。
:識別情報の利用:自動判別は確実なものではなく、
よく[[文字化け]]が起こっていました。そのため、
外部や内部に識別情報を含め(させ)て、
それを使って復号するという手法が提案されてきました。
自動判別の手法も少しずつ改善されていますが、
それでも完全ではないことや、判定にかかる経費の問題がありますし、
識別情報を付加する UA が増えてきたこともあり、
現在では識別情報によって判断するフォーム処理エージェントが増えてきています。

*** 自動判別

[23] [CODE(MIME)[application/x-www-form-urlencoded]] の文字列の符号化方式が不明な場合、
自動判別算法によって決定することがよくあります。
自動判別の方法は WWW でフォームが使われる以前から研究されてきましたが、
フォームのデータは従来の判別対象と比べて非常に短いものが多く、
より難しいものとなっています。

[24] また、 [CODE(MIME)[application/x-www-form-urlencoded]]
では判定の対象となる名前・値が複数個存在しますが、
その一つに対する判定結果を他のすべてに対して使ってよいものかという問題もありました。
現在の実装は一つの [CODE(MIME)[application/x-www-form-urlencoded]]
[[実体]]で複数の符号化方式を混在させることはまずありませんが、
過去にはそうではないものもありました (>>15)。
ですから、ある欄がシフト JIS でも別の欄は日本語 EUC
かもしれず、正確に処理するためにはすべての欄で別々に判定しなければなりませんから、
判定の経費が増大し、しかも判定の材料が少なくなるという悲惨な状況でした。

*** 識別情報の利用

[25] 自動判別にできるだけ頼らず、 UA に識別情報を送らせたり、
一度判定済みの情報を再度利用することによって自動判別の不確実性や経費を削減する方法が古くから考えられてきました。

[5] '''隠し欄を使った方法''': 特定の文字を含めた隠し欄
([[[CODE(HTMLe)[input]]//[CODE(HTML)[hidden]]]])
をフォームに含めておき、提出されたデータの中のその値とあらかじめ用意しておいた
charset ごとのその文字の表現を比較するという方法があります。
たとえば、[SAMP(HTML)[<input type="hidden" name="dot" value="・">]]
をフォームに含めておき、フォーム処理エージェントでは
[SAMP[dot]] の値とあらかじめ用意しておいた [SAMP[・]]
のシフト JIS や日本語 EUC などによる表現と比較します。

この方法は、適当な文字を選べは確実に判定できる優れたものですが、
その情報が他の欄にも通用するとは限らないという問題 (>>24)
があります。この方法が考案された当時実際に欄ごとに別の charset
を用いる実装がありました (>>15) から、
かえって文字化けを誘発する虞がありました。

[27] '''特別な名前を使った方法''':
特定の名前・値の組を charset 名の識別として使います。
例えば、 [[Google]] では [SAMP(URI)[ie=UTF-8]]
のような組を含めることで、一度判別した情報を再利用しているようです。
但し、この使い方はフォームの提出の時点では (UA が対応していないので)
意味がありません。

この方法に UA が対応したものとして、 [CODE(HTML)[[[_charset_]]]]
hack と呼ばれるものがあります。フォームに特定の記述をしておくと、
UA が提出する際に charset 名を [SAMP(URI)[_charset_=ISO-2022-JP]]
のような組として送信してくれます。この方法は最近主要な UA
に実装され、徐々にフォーム処理エージェントでも使われるようになってきています。

[7] '''[CODE(MIME)[charset]] 引数を使った方法''':
[CODE(HTTP)[[[POST]]]] で提出する場合など、
媒体型の引数が利用できる時に、 [CODE(MIME)[[[charset]]]]
引数を使って charset を指定します。

この方法は [[RFC 2070]] や [[WAP]] 
[SRC[[[WML]], [CITE[WAP 日本仕様ガイドライン]]]] 
で提案・規定されていますし、 [[Opera]] などの UA が提出の際に使っています。

[2]
>>27 の方法と似ていますが、 >>27 は[[実体本体]]内の情報であるのに対し、
こちらは実体本体外 ([[実体頭欄]]) の情報ですから、
本体の構文解析より前に情報が得られます。その一方で、
実体頭欄を利用できない [CODE(HTTP)[[[GET]]]] の HTTP URI
のような場所では使えないという致命的な欠点があります。
また、 MIME の定義する [CODE(MIME)[charset]] 引数とは意味的にやや差異があり、
仕様上の問題はないとはいえ、一貫性に欠くとの批判もあります。
(RFC 2070 は、 URI 符号化が 
[ABBR[[[CTE]]] [[CODE(MIME)[[[Content-Transfer-Encoding]]]]]] 
のようなものと考えれば問題なかろうという見解を示しています。)

[29] '''Q: [CODE(MIME)[application/x-www-form-urlencoded]] で使う文字コードは何ですか?'''

A: [CODE(MIME)[application/x-www-form-urlencoded]] 実体自体は [[US-ASCII]]
で記述します。符号化されている内容の文字コードは不定です。
(使用する場面の仕様や実装に依存します。)

詳細: >>11, >>14-15, >>22-, [[提出]], [CODE(HTMLa)[[[accept-charset]]]]

[30] '''Q: HTTP の [CODE(HTTP)[[[Content-Type]]:]] に [CODE(MIME)[[[charset]]]] を指定すればよいのではありませんか?'''

A: そのような実装も存在しますが、標準化されてはいません。また、
MIME の [CODE(MIME)[charset]] 
の仕様と意味的に異なるので望ましくないという考え方もあります。

詳細: >>7-, >>1-, [[[CODE(MIME)[charset]]パラメーター]]

[31] '''Q: 非 ASCII 文字を使う時は [CODE(MIME)[[[multipart/form-data]]]] を使えと言うが、そんなブラウザはないのでは。'''

A: 現代の実用的な Web ブラウザで [CODE(MIME)[multipart/form-data]]
に対応していないなんて考えられません。 HTML の場合は [CODE(HTMLa)[[[enctype]]]]
を [CODE(MIME)[multipart/form-data]] と''著者が''明示しておかないと
[CODE(MIME)[multipart/form-data]] は使われませんよ。

詳細: [CODE(MIME)[[[multipart/form-data]]]], [CODE(HTMLa)[[[enctype]]]], [[提出]]

[32] '''Q: TrackBack は [CODE(MIME)[application/x-www-form-urlencoded]] を使っているが、文字コードを指定できないではないか。欠陥だ。'''

A: そうですね。 [CODE(MIME)[application/x-www-form-urlencoded]]
なんて使うからいけないのです。

関連: [[TrackBack]]

[34] '''Q: 鯖とやり取りするプログラムで、 [CODE(MIME)[application/x-www-form-urlencoded]] と書いてあった部分を [CODE(MIME)[application/x-www-form-urlencoded; charset=UTF-8]] にしたら文字化けが起こらなくなりましたよ。'''

A: たまたまです。相性が良かったのです。
次のときもうまくいくとは限らないこと、
いつまでもうまく動き続けるとは限らないことを肝に銘じておいてください。

関連: >>11, >>14-15, >>22-, [[提出]], [CODE(HTMLa)[[[accept-charset]]]],
[[[CODE(MIME)[charset]]パラメーター]], 
[CODE(MIME)[[[multipart/form-data]]]]

[4] 過去のしがらみが無い HTTP [CODE(HTTP)[[[POST]]]] を使うプロトコル・応用は、
できればこんな時代遅れの形式は使わずに、 [CODE(MIME)[[[multipart/form-data]]]] 
なり [CODE(MIME)[[[application/xml]]]] なり、
他のきちんと標準化された[[媒体型]]を使うべきです。

** RFC 6749 (OAuth 2.0)

[135] [[RFC 6749]] は、 [[HTML 4.01]] を [CODE(MIME)@en[[[application/x-www-form-urlencoded]]]]
の定義であるとしつつ、 [[非ASCII文字]]に対応しない不完全な定義だと述べています
[SRC[>>134]]。

[136] [[RFC 6749]] はまず名前と値を [[RFC 3629]] [[UTF-8]] で[[符号化]]してから[[パーセント符号化]]しなければ[['''ならない''']]
[SRC[>>134]] と規定していました。

;; [139] ただし曖昧な [[HTML4]] を参照しているため、 [[RFC 6749]]
の定義も曖昧無いとはいえません。例えばどの[[文字]]を[[パーセント符号化]]しなければならないかは明確になっていません。

[REFS[
- [134] [CITE@en[RFC 6749 - The OAuth 2.0 Authorization Framework]] ([TIME[2014-12-15 14:15:35 +09:00]] 版) <http://tools.ietf.org/html/rfc6749#appendix-B>
]REFS]

** HTML5

[131] [[HTML]] の[[フォームの提出]]における [CODE(MIME)@en[[[application/x-www-form-urlencoded]]]]
の生成方法は、 [[HTML5]] によってようやく近代的な厳密な定義を得ることとなりました。
ようやくはじめて公式に [[HTML]] の[[フォーム]]から[[非ASCII文字]]を
[CODE(MIME)@en[[[application/x-www-form-urlencoded]]]] で[[提出]]できるようになりました。

[132] それから更に数年遅れて [[URL Standard]] によって [[URL]] 関連の規定の整備が進み、
[[HTML]] の[[フォーム]]と切り離した [CODE(MIME)@en[[[application/x-www-form-urlencoded]]]]
の規定も [[URL Standard]] に含まれることとなりました。それまで [[Webブラウザー]]は
[CODE(MIME)@en[[[application/x-www-form-urlencoded]]]] の生成のみで、
解釈は専ら[[鯖]]側で行われていましたが、 [[URL Standard]] が新たに規定する
[CODE(DOMi)@en[[[URLSearchParams]]]] 関連 [[API]] により[[スクリプト]]でも解釈が行われるようになりました。

[REFS[
- [130] [CITE@en-GB-x-Hixie[Web Forms 2.0]] ([TIME[2009-01-05 20:07:15 +09:00]] 版) <http://www.whatwg.org/specs/web-forms/current-work/#x-www-form-urlencoded>
]REFS]

* 実装

[1] <http://openlab.ring.gr.jp/k16/htmllint/faq.html> によると、古い [[Lynx]] 
は [CODE(MIME)[charset]] パラメーターを付けてしまうようです。 [[Perl]] の古い 
[[CGI]] 用 library である [CODE(file)[[[cgi-lib.pl]]]] はこれに対応していません。

この他にも、 [CODE(HTTP)[[[Content-Type]]:]] 
欄に引数が含まれるとうまく処理できなくなってしまうフォーム処理エージェントがかなり多く存在している模様です。

[6] [WEAK[2003-09-26 07:29:50 +00:00]]
[[Opera]] 7.02 を使ってみましたが、こいつは 
[SAMP(HTTP)[application/x-www-form-urlencoded; charset=utf-8]] 
なんてのを送ってきます。。。

[54]
[CITE[豊島区立図書館のメモ - やればできる子の日記]] ([TIME[2008-10-05 11:21:13 +09:00]] 版) <http://d.hatena.ne.jp/matsuza/20080831/1220177018>

[28] 誤って1文字目に [CODE(URI)[?]] をつける実装もあります。

* 関連

[3] [[Lynx]] は [CODE(MIME)[[[application/sgml-form-urlencoded]]]] 
に対応しています。これは [CODE(URI)[&]] の代わりに [CODE(URI)[;]] を使います。

[8] [CODE(URI)@en[[[mailto:]]]]、[CODE(URI)@en[[[ftp:]]]] などいくつかの [[URL scheme]]
は [[query]] において [CODE(MIME)@en[[[application/x-www-form-urlencoded]]]]
と類似した構文を採用していますが、 [CODE(MIME)@en[[[application/x-www-form-urlencoded]]]]
とはされていません。

[26] [[媒体素片]]は [CODE(MIME)@en[[[application/x-www-form-urlencoded]]]]
と類似した構文を採用していますが、 [CODE(MIME)@en[[[application/x-www-form-urlencoded]]]]
とは細部で異なります。

[40] [CODE(MIME)@en[[[text/plain]]]] や [CODE(MIME)@en[[[text/csv]]]] や
[CODE(MIME)@en[[[application/pdf]]]] などいくつかの [[MIME型]]では[[素片識別子]]に
[CODE(MIME)@en[[[application/x-www-form-urlencoded]]]] と類似した構文を採用していますが、
[CODE(MIME)@en[[[application/x-www-form-urlencoded]]]] とはされていません。

[159] [[フォームの提出]]で [CODE(HTMLa)@en[enctype]] が [CODE(MIME)@en[text/plain]]
の時に使われる形式は、 [CODE(MIME)@en[application/x-www-form-urlencoded]]
から[[パーセント符号化]]を除いたものです。

* メモ

[FIG(amazon)[
Web アプリケーション 開発
]FIG]

[35] '''Q: ファイルをうpできません。ファイル名しか取得できません。'''

A: HTML のフォームでは、ファイルをうpするためには
[CODE(MIME)[application/x-www-form-urlencoded]] は使えません。
[CODE(MIME)[[[multipart/form-data]]]] など他の形式をお使い下さい。

関連: [[[CODE(HTMLe)[input]]//[CODE(HTML)[file]]]],
[CODE(HTMLa)[[[enctype]]]], [CODE(MIME)[[[multipart/form-data]]]]

[55] [CITE@EN[XForms 1.1]]
([TIME[2009-10-20 22:51:54 +09:00]] 版)
<http://www.w3.org/TR/2009/REC-xforms-20091020/#serialize-urlencode>

[56] [CITE[WWW-Talk Jul-Sep 1993: Submitting input-form data to server]]
([TIME[2010-04-10 12:27:04 +09:00]] 版)
<http://1997.webhistory.org/www.lists/www-talk.1993q3/0812.html>

[57] [CITE[XProc: An XML Pipeline Language]]
([TIME[2010-05-11 22:38:07 +09:00]] 版)
<http://www.w3.org/TR/2010/REC-xproc-20100511/#c.www-form-urldecode>

[59] [CITE[IRC logs: freenode / #whatwg / 20100926]]
( ([TIME[2010-10-10 13:13:29 +09:00]] 版))
<http://krijnhoetmer.nl/irc-logs/whatwg/20100926>

[60] [CITE@en[Web Applications 1.0 r6450 Define how to parse the various form submission formats. Register the legacy one. Some editorial tweaks for consistency.]]
( ([TIME[2011-08-15 12:45:00 +09:00]] 版))
<http://html5.org/tools/web-apps-tracker?from=6449&to=6450>

[61] [CITE@en[Web Applications 1.0 r6641 Mention that application/x-www-form-urlencoded;charset does nothing.]]
( ([TIME[2011-10-06 08:08:00 +09:00]] 版))
<http://html5.org/tools/web-apps-tracker?from=6640&to=6641>

[62] [CITE[''''''[''''''ietf-types'''''']'''''' Registration for application/x-www-form-urlencoded]]
( ([TIME[2012-08-08 01:20:11 +09:00]] 版))
<http://www.ietf.org/mail-archive/web/ietf-types/current/msg01711.html>

[63] [CITE[IRC logs: freenode / #whatwg / 20121130]]
( ([TIME[2012-12-12 00:49:30 +09:00]] 版))
<http://krijnhoetmer.nl/irc-logs/whatwg/20121130#l-609>

[64] [CITE[IRC logs: freenode / #whatwg / 20121130]]
( ([TIME[2012-12-12 00:49:30 +09:00]] 版))
<http://krijnhoetmer.nl/irc-logs/whatwg/20121130#l-1057>

[65] [CITE@EN[SPARQL 1.1 Protocol]]
( ([TIME[2013-03-21 20:27:52 +09:00]] 版))
<http://www.w3.org/TR/2013/REC-sparql11-protocol-20130321/#query-via-post-urlencoded>

[66] [CITE[IRC logs: freenode / #whatwg / 20131010]]
( ([TIME[2013-10-14 00:14:43 +09:00]] 版))
<http://krijnhoetmer.nl/irc-logs/whatwg/20131010#l-1183>

[69] ( ([TIME[2011-08-02 14:16:39 +09:00]] 版))
<http://alcme.oclc.org/openurl/docs/pdf/KEV.pdf>

[70] [CITE[Core:Serializations - info:ofi/fmt:kev]]
( ([TIME[2014-07-22 10:46:57 +09:00]] 版))
<http://alcme.oclc.org/openurl/servlet/OAIHandler?verb=GetRecord&metadataPrefix=oai_dc&identifier=info:ofi/fmt:kev>

[71] [CITE@en[Generic syntax]]
( ([[Anne van Kesteren]] 著, [TIME[2013-08-27 23:15:22 +09:00]] 版))
<http://lists.w3.org/Archives/Public/public-media-fragment/2013Aug/0001.html>

[146] [CITE@en[Remove allow non-ASCII-compatible encodings flag · whatwg/html@c485b70]]
([TIME[2016-02-10 21:55:58 +09:00]] 版)
<https://github.com/whatwg/html/commit/c485b70bfe41ed1302c451bc62b58df80cffd325>

[147] [CITE@en[Editorial cleanup for application/x-www-form-urlencoded · whatwg/url@74ea912]]
([TIME[2016-02-10 21:59:38 +09:00]] 版)
<https://github.com/whatwg/url/commit/74ea912c232d5f1596db06cb6297436cec3b0da3>

[148] [CITE@en[Align application/x-www-form-urlencoded serializer with the needs of … · whatwg/url@b174f8f]]
([TIME[2016-02-10 22:02:51 +09:00]] 版)
<https://github.com/whatwg/url/commit/b174f8f2170a4ce6fd4031206e0490eff2b0aa02>

[149] [CITE@en[Adopt a great note about application/x-www-form-urlencoded from HTML · whatwg/url@ef6cda4]]
([TIME[2016-02-11 11:41:33 +09:00]] 版)
<https://github.com/whatwg/url/commit/ef6cda424a60ff435775dcb579839991d9318207>

[150] [CITE@en[Let the URL Standard deal with application/x-www-form-urlencoded · whatwg/html@0fef169]]
([TIME[2016-02-11 11:43:23 +09:00]] 版)
<https://github.com/whatwg/html/commit/0fef169e6fca7433e3aac2a3640b4665b791ff8e>

[151] [CITE@en[Fix logic errors in application/x-www-form-urlencoded · whatwg/url@052a89f]]
([TIME[2016-02-11 12:05:50 +09:00]] 版)
<https://github.com/whatwg/url/commit/052a89fd039ae3e97908eba2d8fdaaac819d6aa2>

[152] [CITE@en[Remove isindex handling from application/x-www-form-urlencoded · whatwg/url@c85fb5d]]
([TIME[2016-04-27 16:46:27 +09:00]] 版)
<https://github.com/whatwg/url/commit/c85fb5d527f822e089aecc9207f077c6b886aed5>

[157] [CITE@en[Fix form submission's encoding algorithms]]
( ([[annevk]]著, [TIME[2016-05-30 23:15:22 +09:00]]))
<https://github.com/whatwg/html/commit/ec42efb1d7c3a2e34db21b8076a8a3f4bd6dfb81>

[167] [CITE@en[XProc 2.0: Standard Step Library]]
([TIME[2016-07-21 14:39:32 +09:00]])
<https://www.w3.org/TR/2016/NOTE-xproc20-steps-20160721/#c.www-form-urldecode>

[168] [CITE@en[Make application/x-www-form-urlencoded encode filenames]]
([[annevk]]著, [TIME[2016-12-29 00:21:45 +09:00]])
<https://github.com/whatwg/url/commit/26caf4927f6c95ba4f56d701ecd8a52fdb664982>

[169] [CITE@en[Parse application/x-www-form-urlencoded using UTF-8 only]]
([[annevk]]著, [TIME[2017-01-17 19:11:02 +09:00]])
<https://github.com/whatwg/url/commit/3fe969679f78c92c353047661b0c4b6797f099f6>

[FIG(quote)[
[FIGCAPTION[
[171] [CITE@ja[Firebase Cloud Messaging サーバーについて  |  Firebase]]
( ([TIME[2017-02-24 05:39:30 +09:00]]))
<https://firebase.google.com/docs/cloud-messaging/server>
]FIGCAPTION]

> application/x-www-form-urlencoded;charset=UTF-8(書式なしテキストの場合) 

]FIG]


[172] [CITE@en[Editorial: use Infra in a/x-www-form-urlencoded]]
([[TimothyGu]]著, [TIME[2017-04-27 18:25:20 +09:00]])
<https://github.com/whatwg/url/commit/1cdcab314ed539a1b26f53a2618ef480708eb297>

[FIG(quote)[
[FIGCAPTION[
[173] [CITE@en[Micropub]]
([TIME[2017-05-21 23:18:57 +09:00]])
<https://micropub.net/draft/#overview-p-1>
]FIGCAPTION]

> All Micropub requests to create posts are sent as UTF-8 x-www-form-urlencoded, multipart/form-data '''['''HTML5''']''', or '''['''JSON''']'''-encoded HTTP requests. 

]FIG]


[FIG(quote)[
[FIGCAPTION[
[174] [CITE@en[Micropub]]
([TIME[2017-05-21 23:18:57 +09:00]])
<https://micropub.net/draft/#form-encoded-and-multipart-requests-p-1>
]FIGCAPTION]

> For x-www-form-urlencoded and multipart/form-data requests, Micropub supports an extension of the standard URL encoding that includes explicit indicators of multi-valued properties. Specifically, this means in order to send multiple values for a given property, you must append square brackets '''['''''']''' to the property name.

]FIG]


[FIG(quote)[
[FIGCAPTION[
[175] [CITE@en[Micropub]]
([TIME[2017-05-21 23:18:57 +09:00]])
<https://micropub.net/draft/#source-content-p-3>
]FIGCAPTION]

> The query can specify the list of properties being requested by setting one or more values for the properties key. If more than one is specified, use array bracket notation for each name, according to '''['''HTML5''']''' URL encoding.

]FIG]


[176] [CITE@en[Remove _charset_ handling from application/x-www-form-urlencoded]]
([[tkent-google]]著, [TIME[2018-04-27 17:23:44 +09:00]])
<https://github.com/whatwg/url/commit/5c0d2ec09ec16099e5c453d088fea9b8ba0154a5>

[177] [CITE@en[Remove _charset_ handling. by tkent-google · Pull Request #382 · whatwg/url]]
([TIME[2018-05-02 12:45:35 +09:00]])
<https://github.com/whatwg/url/pull/382>

[178] [CITE@en[Move _charset_ handling to construct the form data set]]
([[tkent-google]]著, [TIME[2018-04-27 17:25:35 +09:00]])
<https://github.com/whatwg/html/commit/8c212e549607a41b6d40d953b47d9f3e749533f3>

[179] [CITE@en[Move _charset_ handling from "multipart/form-data encoding algorithm"… by tkent-google · Pull Request #3645 · whatwg/html]]
([TIME[2018-05-02 12:50:54 +09:00]])
<https://github.com/whatwg/html/pull/3645>

[180] [CITE@en[Remove 'type' from from data entries]]
([[tkent-google]]著, [TIME[2018-05-08 18:08:48 +09:00]])
<https://github.com/whatwg/url/commit/acc2bf4a8e67fb13523f4ee35ff32be922eb9142>

[181] [CITE@en[Remove 'type' from from data entries. by tkent-google · Pull Request #384 · whatwg/url]]
([TIME[2018-05-10 12:19:20 +09:00]])
<https://github.com/whatwg/url/pull/384>

[182] [CITE@en[795733 - '&' and ';' should not be percent-encoded in URL queries - chromium - Monorail]]
([TIME[2018-05-26 00:03:48 +09:00]])
<https://bugs.chromium.org/p/chromium/issues/detail?id=795733>

[183] [CITE@en[percent-encode ' in queries of URLs with special schemes by achristensen07 · Pull Request #395 · whatwg/url]]
([TIME[2018-06-11 23:50:31 +09:00]])
<https://github.com/whatwg/url/pull/395>


[184] 
[TIME[2023-02-23T02:49:39.00Z]]
<https://lab.ndl.go.jp/dataset/ndlocr/text_recognition/ndlenfixed64-mj0-synth1.pth>

なぜか [CODE[Content-Type]] が
[CODE[application/x-www-form-urlencoded; charset=utf-8]]。
中身はぜんぜん違う。

