[23] chunked
は、
payload body を複数の塊 (chunk) の連続体として表現する転送符号化です。
[24] 塊のデータの長さはそれぞれの塊に指定します。そのため、 事前に payload body 全体の長さが分からなくても、 準備のできたデータから順に送信を開始することができますし、 どこまでが当該メッセージに含まれるデータの一部なのかを明確にすることができます。
[414] HTTP/1.1 は chunked
への対応を義務付けています。
HTTP/0.9、HTTP/1.0、HTTP/2 では使えません。
[415] chunked
符号化されている場合、
メッセージ本体は、塊、トレーラー部、CRLF
によって構成されます >>413。
[419] 塊は、最後の塊だけ特別な形になります。 それより前に任意の個数の塊を置けます。
[416] 最後以外の塊は、サイズ、拡張、CRLF、データ、CRLF によって構成されます >>413。
[420] 最後の塊は、サイズ、拡張、CRLF によって構成されます >>413。
[417] サイズは、1文字以上の十六進数字の列によって構成され、 データのオクテット数を16進数として表しています >>413。 ただし最後の塊のサイズは、 0 でなければいけません >>413。
[30] chunked
転送符号化は、
chunked
という値を Transfer-Encoding:
ヘッダーに指定することにより、メッセージ本体に適用することができます。
[49]
Transfer-Encoding:
の制限のため、 HTTP/1.1 でのみ使うことができます。
また要求で利用できる場面は限られます。
[27] chunked
を同じメッセージ本体に複数回適用してはなりません
>>25。
[28] 複数の転送符号化が適用される時は、chunked
を最後に適用しなければなりません >>25。
[29] chunked
以外の転送符号化を適用するときは、
接続を閉じることによってメッセージを終端するのでなければ、
最後に chunked
を適用しなければなりません >>25。
[32] chunked
以外の転送符号化が用いられている場合を除き、
事前にメッセージ本体の長さが分かっている時には、 chunked
よりも Content-Length:
を使うべきです。
実装によっては chunked
に対応していても、
411
で応答することがあります。 >>31
[424] 拡張は、 ;
、名前、=
、値を並べたものです。
ただし =
と値は省略できます。 >>413
ヘッダー内ではありませんから、 OWS は認められていません。
[425] 名前は字句です。値は字句または引用文字列です。 >>413
[426] 拡張は、署名やハッシュ値を入れたり、メッセージのサイズをランダムに変化させたり、 long polling など特別な目的で使ったりすることが想定されているようです。 >>413 しかし現時点で利用例はありません。
[427] 受信者は、認識できない拡張を無視しなければなりません。
鯖は、要求中の拡張の合計長を適当と考える長さに制限し、
それを超えたら 4xx
を返すべきです。 >>413
[26] HTTP/1.1 受信者は、 chunked
転送符号化を構文解析して復号できなければなりません >>25。
chunked
符号化もありませんでした。
HTTP/1.0 と分かっている相手に chunked
符号化を使用することは認められていませんし、
意図通り解釈されることは期待できません。ただし HTTP/1.0
をプロトコルの版とするメッセージで Transfer-Encoding:
ヘッダーが含まれていて chunked
が指定されている時に、どう解釈するべきなのかは明確ではありません。[412] 長さが零の塊を受信していない場合、メッセージは不完全です >>31。
[15] 入力が妥当な chunked
符号化されたデータになっていないときどう処理するべきなのかは不明瞭ですが、
不完全メッセージとして扱うべきであるとの言及があります >>16。
[39] Firefox と IE は、復号できるところまで復号して使うようです。 ただし IE では、復号できた部分がある程度たまらないと、エラーとして扱います。 Chrome は最後まで復号できないとエラーとして扱うようです (XHR ではネットワークエラー、navigate では復号できた量により空またはネットワークエラーとして扱うようです)。
[40] 壊れた chunk に遭遇した時、 IE はできるだけ得られたデータを利用しようとし、 Firefox はその chunk の前まででやめるようです。 しかしネットワークエラーになる場合もあるなど、細かく見ていくといろいろありそうです。
[41] Firefox と Chrome は省略可能な CR とその後の LF を改行とします。 IE は CRLF のみ改行とします。
[42] Firefox と IE は十六進数の後の十六進数以外をすべて無視します。
Chrome は ;
とそれ以降を無視しますが、 ;
の前に空白以外があると、
エラーとして扱います。最後の塊については Firefox も ;
の前にあるとエラーとして扱います。
[43] Chrome は trailer 部のヘッダー部としての構文エラー (空行がないとか、 ヘッダーの後改行なしに接続が切断されたとか) をネットワークエラーとします。 IE と Firefox は無視します。
[45] Windows の IE や Chrome は、 chunked の送信方法
(TCP セグメントの分割方法) 次第で、正しく処理できなくなることがあるようです。
例えば chunk ごとにサイズの行、データ、改行とそれぞれ別々に送信する場合は、
最初の chunk のサイズの行が 1461 バイト以上無いと、
最初のいくつかの chunk のデータを受信し、それ以後は無視し、接続が閉じられた時点で受信完了とするようです。
chunk ごとにまとめて送信するなら、このようなおかしな動作はしないようです。
TCP セグメントの PSH
フラグが立っていても、そうなります。
おそらく、受信した OS またはアプリケーション側のバッファリングの問題と、
EOF 受信時に未処理の受信データを捨てるためにそのような結果となるのでしょう。
なお 1460 バイトというのはちょうどイーサーネットにおける MSS
です。
[1] 塊 (chunked) 符号化は、 HTTP/1.1 で導入された転送符号化です。 (転送符号化自体、 HTTP/1.1 で導入されたものです。また現時点で利用出来る唯一の転送符号化でもあります。)
[2] HTTP/1.1 は持続可能接続 (Keep-Alive) を導入しましたが、このためには内容の長さ (あるいは内容の終了の位置) を知る必要があります。 HTTP は非常に単純なプロトコルで、 HTTP/1.0 以前には終了の位置を知る方法はありませんでした。 その代わりに、接続が切れたらそこで終わりでした。 (Content-Length:欄があれば、切れた接続が正常切断だったのかを判断出来ます。)
しかし持続可能接続ではこの方法は使えません。 そこで導入されたのがこの塊転送符号化です。 HTTP/1.1 では塊転送符号化の実装が必須とされています。 (だけど実装が面倒 (というか見たらやる気を失くす。) なので、塊符号化を実装せず、それだけのために HTTP/1.1 非対応の UA も少なくはありません。)
[3] もちろん、 Content-Length:欄を必ずつけることにすればそれで長さは特定できるのですが、 CGI 出力のように長さが事前に定まらない (定まるのを待っていたら時間が掛かる可能性のある) ことがありますので不便です。
[4] 塊符号化は、符号化の内容を任意の長さの塊に分け、それぞれの塊の最初に塊の長さを書いておきます。一番最後におまけで長さ 0 と書いた塊をつけときます。これだけです。実はそんなに厄介でもありません。
[5] この塊符号化に関する部分の実装の不具合が問題になったこともありました。 (Apache などの古い版を使っている人は新しい版にしましょう。)
[431] chunked-extension に対応していなかった実装は他にもありました >>430。
[22] IE9 Beta Minor Changes List - EricLaw's IEInternals - Site Home - MSDN Blogs ( 版) <http://blogs.msdn.com/b/ieinternals/archive/2010/09/15/ie9-beta-minor-change-list.aspx>
[19] TAKESAKO @ Yet another Cybozu Labs: ニコニコ動画勉強会に行ってきました ( 版) <http://labs.cybozu.co.jp/blog/takesako/2007/04/nicovideo.html>
[20] Chunked + Gzip | Apache | Users (Referenced: ) <http://www.gossamer-threads.com/lists/apache/users/356732>
[432] draft-maes-lemonade-http-binding-04 - IMAP and SMTP HTTP Binding ( ( 版)) <http://tools.ietf.org/html/draft-maes-lemonade-http-binding-04#section-2.1.2>
[433] draft-maes-lemonade-tcp-challenged-environments-01 - Lemonade in TCP Challenged Environments ( ( 版)) <https://tools.ietf.org/html/draft-maes-lemonade-tcp-challenged-environments-01#page-7>
[434] draft-maes-lemonade-p-imap-12 - Push Extensions to the IMAP Protocol (P-IMAP) ( ( 版)) <http://tools.ietf.org/html/draft-maes-lemonade-p-imap-12#page-47>
[436] RFC 3507 - Internet Content Adaptation Protocol (ICAP) ( ( 版)) <http://tools.ietf.org/html/rfc3507#section-4.4>
[437] RFC 4387 - Internet X.509 Public Key Infrastructure Operational Protocols: Certificate Store Access via HTTP ( ( 版)) <http://tools.ietf.org/html/rfc4387#section-2.5.4>
[37] chunking without chunking (Adrien de Croy 著, 版) <https://lists.w3.org/Archives/Public/ietf-http-wg/2009AprJun/0717.html>
[38] How to enable chunked transfer encoding with IIS ( 版) <https://support.microsoft.com/en-us/kb/278998>
[46] Stream-based requests (Request with ReadableStream) (yutakahirano著, ) <https://github.com/whatwg/fetch/commit/0c470b5860fe690b1136b0242951f682405103cc>
[48] DocuSign REST API Guide - Chunked Transfer-Encoding Support () <https://www.docusign.com/p/RESTAPIGuide/RESTAPIGuide.htm#Chunked Transfer-Encoding Support/Chunked Transfer-Encoding Support.htm%3FTocPath%3D_____8>
[50]
KeepAlive On な Apache+mod_php で HTTP/1.0 クライアントに HTTP/1.1 を返すとタイムアウトを待ってしまう - ngyukiの日記 ( 版) <http://ngyuki.hatenablog.com/entry/2017/08/02/081959>
には、 HTTP/1.0 で要求を送信しているのに
HTTP/1.1 で Transfer-Encoding: chunked
の応答が返される事例が紹介されています。 Apache 単体では再現できなかったので、
PHP の挙動でしょうか。
[52] Chunked upload Cronet API. - Google グループ () <https://groups.google.com/a/chromium.org/forum/#!topic/net-dev/yvmWG4hexBE>