[12] [[電子メール]]の[[ヘッダー]]内では元来あらゆる[[字句]]間に[[空白]]や[[注釈]]が認められていました。
[[電子メール]]に強い影響を受けた [[HTTP]] でも、多くの場所で[[空白]]を認めていました。
[[電子メール]]でも [[HTTP]] でも、仕様の改訂により徐々に[[空白]]の使用方法が限定的になってきています。

* 電子メールにおける空白

[1] Linear white space (線形空白)。

- rfc2068.LWS = [CRLF] 1*( SP | HT )

[2]
[[RFC 822]] で使われておりましたが、
[[RFC 2822]] では [CODE(ABNF)[[[FWS]]]] 
(や [CODE(ABNF)[[[CFWS]]]]) に全面的に置き換えられています。

[55] 
[DFN[[CODE[FWS]]]] は、[[空白]]を表しています。
[CODE[U+0020]] や [CODE[U+0009]] を使うことができるのに加えて、
直後に [CODE[U+0020]] や [CODE[U+0009]] が続く場合に、 [CODE[U+000D]] [CODE[U+000A]]
([[CRLF]]) を使うことができます。これは[[折り畳み]]と呼ばれているもので、
1つの[[ヘッダー]]を複数[[行]]で表したい時に使います。

[56] 
[DFN[[CODE[CFWS]]]] は、 [CODE[FWS]] に加えて、[[注釈]]を使うことが認められるものです。


[REFS[
- [4] [CITE@en[RFC 822 - STANDARD FOR THE FORMAT OF ARPA INTERNET TEXT MESSAGES]] ([TIME[2014-03-08 23:19:55 +09:00]] 版) <http://tools.ietf.org/html/rfc822#section-3.1.4>
]REFS]

[5] >>4 3.1.4. は[[字句]]間に [CODE(ABNF)@en[[[linear-white-space]]]] を挿入して良いとしています。

[REFS[
- [6] [CITE@en[RFC 822 - STANDARD FOR THE FORMAT OF ARPA INTERNET TEXT MESSAGES]] ([TIME[2014-03-08 23:19:55 +09:00]] 版) <http://tools.ietf.org/html/rfc822#section-3.4.2>
]REFS]

[7] >>6 で [CODE(char)[[[U+0009]]]] の使用は[RUBYB[勧められない]@en[discouraged]]とされています。

[REFS[
- [8] [CITE@en[RFC 2822 - Internet Message Format]] ([TIME[2014-03-08 23:10:45 +09:00]] 版) <http://tools.ietf.org/html/rfc2822#section-3.2.3>
- [9] [CITE@en[RFC 2822 - Internet Message Format]] ([TIME[2014-03-08 23:10:45 +09:00]] 版) <http://tools.ietf.org/html/rfc2822#section-4.2>
- [11] [CITE@en[RFC 5322 - Internet Message Format]] ([TIME[2014-05-13 12:04:08 +09:00]] 版) <http://tools.ietf.org/html/rfc5322#section-3.2.2>
]REFS]

[10] [[RFC 2822]] では [[WSP]] のみの行の使用は禁止されていますが、理解できなければなりません [SRC[>>9]]。

** 折り畳み

[21] 折り畳まれた2行目以降の部分に [CODE(822)[:]] という文字が含まれていると、へんちくりんな [[MTA]] が勝手にその直後に [CODE(char)[[[SP]]]] を挿入しちゃったりすることがあるんだそうです。 (そんなのが21世紀になっても生き残っているとは!)

[22] >>21 参考 : ''はじめてのにっき(2003-09-05)'' <http://hajimeteno.alib.jp/diary/?date=20030905>, <IW:mew-dist:23997>

[23] >>21-22 特に [CODE(MIME)[[[multipart/*]]]] の [CODE(MIME)[[[boundary]]]] 引数なんかがそれに引っ掛かると深刻なので、 [[Mew]] では境界文字列に [CODE(MIME)[:]] があったら [CODE(MIME)[_]] に置き換えるみたいです。

* HTTP における空白

[13] [[HTTP]] における[[空白]]は、 [DFN[[[OWS]]]] (省略可能空白)、
[DFN[[[RWS]]]] (必須空白)、[DFN[[[BWS]]]] (「悪い」空白) に分類されています [SRC[>>31]]。

[32] また、[RUBYB[行折り畳み]@en[line folding]]として、
[[改行]]と[[空白]]を続けることで[[欄値]]を複数行に分割することもできました。
ただし現在はその[[生成]]が禁止されています。

** 仕様書

[REFS[
- [31] [CITE@en[RFC 7230 - Hypertext Transfer Protocol (HTTP/1.1): Message Syntax and Routing]] ([TIME[2014-06-07 01:59:35 +09:00]] 版) <https://tools.ietf.org/html/rfc7230#section-3.2.3>
- [24] [CITE@en[RFC 7230 - Hypertext Transfer Protocol (HTTP/1.1): Message Syntax and Routing]] ([TIME[2014-06-07 01:59:35 +09:00]] 版) <https://tools.ietf.org/html/rfc7230#page-23>
- [40] [CITE@en[RFC 7230 - Hypertext Transfer Protocol (HTTP/1.1): Message Syntax and Routing]] ([TIME[2014-06-07 01:59:35 +09:00]] 版) <https://tools.ietf.org/html/rfc7230#section-3.2.4>
- [14] [CITE@en[RFC 6454 - The Web Origin Concept]] ([TIME[2011-12-12 09:13:37 +09:00]] 版) <http://tools.ietf.org/html/rfc6454#section-2.2>
- [15] [CITE@en[RFC 6265 - HTTP State Management Mechanism]] ([TIME[2012-03-01 09:57:02 +09:00]] 版) <http://tools.ietf.org/html/rfc6265#section-2.2>
]REFS]

** 文脈

[39] [[空白]]は[[欄値]]中の色々な場所で認められています。場所により、
[[OWS]]、[[RWS]]、[[BWS]] のいずれかが指定されています。 [[SP]]
と指定されていることもあります。

[25] [[欄値]]には[[行折り畳み]] ([DFN[[CODE(ABNF)@en[[[obs-fold]]]]]])
が含まれることがあります [SRC[>>24]]。ただし[[廃止]]された構文とされており、
[[生成]]してはなりません。

;; [41] [CODE(MIME)@en[[[message/http]]]] 以外では[RUBYB[非推奨]@en[deprecated]]
[SRC[>>40]]、 [CODE(MIME)@en[[[message/http]]]] を意図した場合を除き禁止
[SRC[>>40]] ともされており、完全に禁止されているわけではないとも解釈できます。

[43] 次の場面では [CODE(charname)@en[[[SP]]]] そのものが構文上求められています。
[FIG(short list)[
- [[開始行]]
- [CODE(HTTP)@en[[[Content-Range:]]]]
- [CODE(HTTP)@en[[[Warning:]]]]
- [[challenge]]
- [[credentials]]
- [[cookie-string]]
]FIG]

** 構文

[34] [[空白]] ([[OWS]], [[RWS]], [[BWS]]) は、いずれも任意の文字数の
[[SP]] や [[HTAB]] です [SRC[>>31]]。

[35] [[OWS]] は、可読性のために好ましい時は [[SP]] 1つとして[[生成]]する[['''べきです''']]。
それ以外では、非妥当だったり望まなかったりする[[プロトコル要素]]をその場でメッセージをフィルタリングするために必要な場合を除き、
[[生成]]する[['''べきではありません''']]。 [SRC[>>31]]

;; [36] 後者がいつなのかよくわかりませんが...

;; [18] [[RFC 6265]], [[RFC 6454]] の定義では、[[OWS]] は生成しないか、
または単一の [CODE(ABNF)[[[SP]]]] とする[['''べきです''']] [SRC[>>14, >>15]]。

[FIG(railroad)[
= ?
== [CODE(char)[[[U+0020]]]]
]FIG]

[37] [[RWS]] は、 [[SP]] 1つとして[[生成]]する[['''べきです''']] [SRC[>>31]]。
そうでなくても必ず1文字は必要です [SRC[>>31]]。

[FIG(railroad)[
= [CODE(char)[[[U+0020]]]]
]FIG]

[38] [[BWS]] は、[[生成]]しては[['''ならず''']]、
[[受信者]]は解釈の前に削除しなければ[['''なりません''']] [SRC[>>31]]。

[FIG(railroad)[

]FIG]

[26] [[行折り畳み]]は、 [[CRLF]] の後1文字以上の [[SP]] または [[HTAB]] とされています
[SRC[>>24]]。

[FIG(railroad)[
= [CODE(char)[[[U+000D]]]]
= [CODE(char)[[[U+000A]]]]
= +
== |
=== [CODE(char)[[[U+0020]]]]
=== [CODE(char)[[[U+0009]]]]
]FIG]

** 意味

[19] [[OWS]] は零個以上の[[線形空白]]が現れて良い場所で使います。 [SRC[>>14, >>15]]

** 処理モデル

[42] [[鯖]]は、 [CODE(MIME)@en[[[message/http]]]] 以外の[[要求メッセージ]]の[[行折り畳み]]を受信した場合、
[CODE(HTTP)[[[400]]]] を (できれば[[行折り畳み]]は受け付けられない旨の[[表現]]と共に)
返すか、または[[行折り畳み]]を1つ以上の [[SP]] 
に置き換えてから解釈するか、[[下流]]に[[転送]]するかしなければ[['''なりません''']]
[SRC[>>31]]。

[401] [[串]]や[[関門]]は、 [CODE(MIME)@en[[[message/http]]]] 以外の[[応答メッセージ]]の[[行折り畳み]]を受信した場合、
その[[メッセージ]]を捨てて [CODE(HTTP)[[[502]]]] を
(できれば[[行折り畳み]]は受け付けられない旨の[[表現]]と共に) 返すか、
または[[行折り畳み]]を1つ以上の [[SP]] 
に置き換えてから解釈するか、[[下流]]に[[転送]]するかしなければ[['''なりません''']]
[SRC[>>31]]。

[503] [[利用者エージェント]]は、 [CODE(MIME)@en[[[message/http]]]] 以外の[[応答メッセージ]]の[[行折り畳み]]を受信した場合、
[[行折り畳み]]を1つ以上の [[SP]] 
に置き換えてから解釈しなければ[['''なりません''']] [SRC[>>31]]。

;;
[20] [[RFC 6265]], [[RFC 6454]] の定義では、複数の [[OWS]] [[オクテット]]は、
[[欄値]]を解釈する前に、
または下流に[[転送]]する前に単一の [CODE(ABNF)[[[SP]]]]、または同じ個数の [CODE(ABNF)[[[SP]]]]
に置換する[['''べきです''']]。 [SRC[>>14]]

** 歴史

[27] [[RFC 2616]] 世代までは、構文上 [CODE(ABNF)[[[LWS]]]] ではなく [CODE(ABNF)[[[SP]]]] 
を使って定義されているところでは、[[行折り畳み]]が使えないとも解釈できました。

[EG[
例えば、
- [28] [[誰何]]の [[auth-scheme]] と [[auth-param]] の間
- [29] [[credentials]] の [[auth-scheme]] と [[auth-param]] の間

... は [[SP]] を使って定義されています。
]EG]

[504] [[RFC 7230]] は[[行折り畳み]]を [[SP]] に置き換えてから解釈が行われるとしており、
>>27 のような箇所でも[[行折り畳み]]が使えると明確になっています。

;; [44] [[開始行]]は[[ヘッダー]]ではありませんから、そもそも[[行折り畳み]]は使えません。

[33] [[RFC 7230]] の開発途中に出版された [[RFC 6265]], [[RFC 6454]]
は、 [[RFC 7230]] とは少し違った [[OWS]] を定義していました。
いずれも定義は微妙に異なっていますが、実態としては同じような規定です。

[FIG[
[FIGCAPTION[
[16] [CODE(ABNF)[[[OWS]]]] の [[ABNF]] 構文 [SRC[>>14]]
]FIGCAPTION]

[PRE(ABNF code)[
   OWS            = *( SP / HTAB / obs-fold )
                  ; "optional" whitespace
   obs-fold       = CRLF ( SP / HTAB )
                  ; obsolete line folding
]PRE]
]FIG]

[FIG[
[FIGCAPTION[
[17] [CODE(ABNF)@en[[[OWS]]]] の [[ABNF]] 構文 [SRC[>>15]]
]FIGCAPTION]

[PRE(ABNF code)[
   OWS            = *( [ obs-fold ] WSP )
                    ; "optional" whitespace
   obs-fold       = CRLF
]PRE]
]FIG]

* CGI における空白

[1] 
[PRE[
      SP            = <space character>
      HT            = <horizontal tab character>
      NL            = <newline>
      LWSP          = SP | HT | NL
]PRE]

;; [3] [[CGI]]では実際の[[ビット列]]は[[システム定義]]とされています。特に、 [[NL]]
は1[[バイト]]である必要がないことが明記されています。

[30] [[CGI応答]]では[[折り畳み]]は認められていません。

** 仕様書

[REFS[
- [2] [CITE@en[RFC 3875 - The Common Gateway Interface (CGI) Version 1.1]] ([TIME[2011-11-20 06:09:05 +09:00]] 版) <http://tools.ietf.org/html/rfc3875#page-7>
]REFS]

[505] [CITE[Introduce concept-header-list-combine for XMLHttpRequest · 6965d6e · whatwg/fetch]]
( ([TIME[2014-06-24 06:28:35 +09:00]] 版))
<https://github.com/whatwg/fetch/commit/6965d6e4e9cc2705f1ca2b230a77747cc1fa2626>

[45] [CITE@en[Reference the new HTTP RFCs. Normalize header values. Fixes #99, #100… · whatwg/fetch@6c00fe2]]
([TIME[2015-08-11 11:37:31 +09:00]] 版)
<https://github.com/whatwg/fetch/commit/6c00fe28e7a361d2b7e0dda776ebccfaa4c439a5>

[46] [CITE@en-US[Fetch Standard]]
([TIME[2015-08-11 00:32:44 +09:00]] 版)
<https://fetch.spec.whatwg.org/#http-whitespace-bytes>

[47] [CITE[Wireless Application Protocol Wireless Session Protocol Specification]]
([TIME[2013-09-23 14:21:18 +09:00]] 版)
<http://technical.openmobilealliance.org/tech/affiliates/wap/WAP-230-WSP-20010705-a.pdf>

[48] [CITE@en[Use `,` rather than `, ` for the combine operation]]
([[annevk]]著, [TIME[2016-08-10 16:22:25 +09:00]])
<https://github.com/whatwg/fetch/commit/c21f8bd50ef9e919e6b1003a6dfbe29a7195d57a>

[FIG(quote)[
[FIGCAPTION[
[49] [CITE[PSGI - search.cpan.org]]
([TIME[2016-10-06 15:37:03 +09:00]])
<http://search.cpan.org/dist/PSGI/PSGI.pod>
]FIGCAPTION]

> If there are multiple header lines sent with the same key, the server should treat them as if they were sent in one line and combine them with , , as in RFC 2616.

]FIG]


[50] [CITE@en[Stop lowercasing header names]]
([[annevk]]著, [TIME[2017-02-22 20:01:22 +09:00]])
<https://github.com/whatwg/fetch/commit/5869c43a27fff06c6dfc228fe1288018f7f2168d>

[51] [CITE@en[Change combine and combined value to use 0x2C 0x20 (#504)]]
([[annevk]]著, [TIME[2017-03-11 03:09:51 +09:00]])
<https://github.com/whatwg/fetch/commit/d9307bde55a32dee1a82207202f712fc3c8fde8b>

[52] [CITE@en[Align header handling with Fetch]]
([[annevk]]著, [TIME[2017-03-13 16:20:43 +09:00]])
<https://github.com/whatwg/xhr/commit/a6e79810a381b8e336570da797967c4b34e0c6b1>

[53] [CITE@en[Get multiple headers as an aray rather than a combined value? · Issue #506 · whatwg/fetch]]
([TIME[2017-03-15 17:05:51 +09:00]])
<https://github.com/whatwg/fetch/issues/506>

[54] [CITE[Release Notes for Safari Technology Preview 26 | WebKit]]
([TIME[2017-04-19 00:12:53 +09:00]])
<https://webkit.org/blog/7474/release-notes-for-safari-technology-preview-26/>

[57] [CITE@en[Define parsing for X-Content-Type-Options: nosniff in detail]]
([[annevk]]著, [TIME[2018-11-01 18:14:30 +09:00]])
<https://github.com/whatwg/fetch/commit/32c7b1c76a43ea96b8663628b891b339553ae114>

[58] [CITE@en[What does "combined value" return for a name not in the header list? · Issue #752 · whatwg/fetch]]
([TIME[2019-03-04 19:55:33 +09:00]])
<https://github.com/whatwg/fetch/issues/752>

[59] [CITE@en[Define parsing for X-Content-Type-Options in detail by annevk · Pull Request #818 · whatwg/fetch]]
([TIME[2019-03-04 19:58:29 +09:00]])
<https://github.com/whatwg/fetch/pull/818>

[60] [CITE@en[Add HTTP whitespace back for MIME types]]
([[annevk]]著, [TIME[2018-11-12 18:30:24 +09:00]])
<https://github.com/whatwg/fetch/commit/a243f1f8af10f78ead83953bfb0f1c6ee21cb8a1>

[61] [CITE@en[Add HTTP whitespace back for MIME types by annevk · Pull Request #828 · whatwg/fetch]]
([TIME[2019-04-15 18:41:05 +09:00]])
<https://github.com/whatwg/fetch/pull/828>

[62] [CITE@en[Use HTTP rather than ASCII whitespace by annevk · Pull Request #90 · whatwg/mimesniff]]
([TIME[2019-04-15 18:41:26 +09:00]])
<https://github.com/whatwg/mimesniff/pull/90>

[63] [CITE@en[Use HTTP whitespace rather than ASCII whitespace]]
([[annevk]]著, [TIME[2018-11-13 20:11:52 +09:00]])
<https://github.com/whatwg/mimesniff/commit/126286ab2dcf3e2d541349ed93539a88bf394ad5>

[64] [CITE@en[MIME type parsing: stop treating 0x0C as whitespace · Issue #89 · whatwg/mimesniff]]
([TIME[2019-04-15 18:44:07 +09:00]])
<https://github.com/whatwg/mimesniff/issues/89>