[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 と書いた塊をつけときます。これだけです。実はそんなに厄介でもありません。
The chunked encoding modifies the body of a message in order to transfer it as a series of chunks, each with its own size indicator, followed by an OPTIONAL trailer containing entity-header fields. This allows dynamically produced content to be transferred along with the information necessary for the recipient to verify that it has received the full message.
chunked (塊) 符号化は、メッセージの本体を、転送のためにいじって 塊の連続とします。各塊は大きさ指示が付きますし、 最後には任意で、 trailer (おまけ) 実体頭欄を続けることが出来ます。 これにより、動的に生成した内容が、受信者が完全なメッセージを受け取ったか確認するのに必要な情報と共に転送出来るようになります。
Chunked-Body = *chunk last-chunk trailer CRLF
chunk = chunk-size [ chunk-extension ] CRLF chunk-data CRLF chunk-size = 1*HEX last-chunk = 1*("0") [ chunk-extension ] CRLF
chunk-extension= *( ";" chunk-ext-name [ "=" chunk-ext-val ] ) chunk-ext-name = token chunk-ext-val = token | quoted-string chunk-data = chunk-size(OCTET) trailer = *(entity-header CRLF)
The chunk-size field is a string of hex digits indicating the size of the chunk-data in octets. The chunked encoding is ended by any chunk whose size is zero, followed by the trailer, which is terminated by an empty line.
chunk-size (塊長) 欄は、 chunk-data の長さをオクテット単位で表す 16進数字の文字列です。 chunked (塊)符号化は、長さ 0 の chunk (塊)、それに続く, 空行で終わる trailer (おまけ)で終わります。
訳注: 上記段落での追加部分は Errata (>>8) から補った。
The trailer allows the sender to include additional HTTP header fields at the end of the message. The Trailer header field can be used to indicate which header fields are included in a trailer (see section 14.40).
trailer により、送信者はメッセージの終わりに追加の HTTP 頭領域を 入れることが出来ます。 Trailer 頭領域は trailer に含まれている 頭領域を示すのに使うことが出来ます。 (14.40節参照)
A server using chunked transfer-coding in a response MUST NOT use the trailer for any header fields unless at least one of the following is true:
応答に chunked 転送符号化を使うサーバーは 次の条件の一つ以上を満たさずに trailer を使ってはいけません。
a)the request included a TE header field that indicates "trailers" is acceptable in the transfer-coding of the response, as described in section 14.39; or,
a) 14.39節で説明するように、要求が、 「trailers」を応答の転送符号化で 使っても良いと示す TE 頭領域を含んでいる場合
b)the server is the origin server for the response, the trailer fields consist entirely of optional metadata, and the recipient could use the message (in a manner acceptable to the origin server) without receiving this metadata. In other words, the origin server is willing to accept the possibility that the trailer fields might be silently discarded along the path to the client.
b) サーバーが、応答の原サーバーで、 trailer 領域が 完全に任意のメタ情報であって、受信者がそのメタ情報を受信せずとも (原サーバー的に認められる方法で) メッセージを使うことが出来る場合。 別の言い方をすると、原サーバーが、 trailer 領域がクライアントへの 経路中に黙って捨てられる可能性があることを認める意思があるという場合
This requirement prevents an interoperability failure when the message is being received by an HTTP/1.1 (or later) proxy and forwarded to an HTTP/1.0 recipient. It avoids a situation where compliance with the protocol would have necessitated a possibly infinite buffer on the proxy.
この要求事項は、メッセージが HTTP/1.1 (以上) の串が受信して HTTP/1.0 受信者に転送される時に、相互通信性的に失敗するのを 防ぐものです。これにより、このプロトコルに従うことが、 串で不定バッファーが必要になるかもしれない状況を避けることが出来ます。
An example process for decoding a Chunked-Body is presented in appendix 19.4.6.
塊本体の復号処理の例を附属書 19.4.6 に示しました。
All HTTP/1.1 applications MUST be able to receive and decode the "chunked" transfer-coding, and MUST ignore chunk-extension extensions they do not understand.
全ての HTTP/1.1 応用は「chunked」転送符号化を受信して復号する ことが出来なければならず、理解できない chunk-extension (塊拡張) を無視しなければなりません。
HTTP/1.1 introduces the Transfer-Encoding header field (section
14.4014.41). Proxies/gateways MUST remove any transfer-coding prior to forwarding a message via a MIME-compliant protocol.
[17] HTTP/1.1 は Transfer-Encoding 頭欄を導入しました。
串・関門は MIME に従うプロトコルにメッセージを転送する前に
transfer-coding
を解かなければなりません。
A process for decoding the "chunked" transfer-coding (section 3.6) can be represented in pseudo-code as:
[18] "chunked" transfer-coding の復号過程は擬似 code で次のように表せます。
length := 0 read chunk-size, chunk-extension (if any) and CRLF while (chunk-size > 0) { read chunk-data and CRLF append chunk-data to entity-body length := length + chunk-size read chunk-size and CRLF } read entity-header while (entity-header not empty) { append entity-header to existing header fields read entity-header } Content-Length := length Remove "chunked" from Transfer-Encoding
長さ := 0 chunk-size と chunk-extension (あれば) と CRLF を読む (chunk-size > 0) の間 { chunk-data と CRLF を読む chunk-data を entity-body に付加する 長さ := 長さ + chunk-size chunk-size と CRLF を読む } entity-header を読む (entity-header が空でない) の間 { entity-header を既存の頭欄に付加 entity-header を読む } Content-Length := 長さ "chunked" を Transfer-Encoding から削除
[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>
Apache Tomcat は、チャンク転送コーディング (chunked transfer coding) のチャンク拡張 (chunk extension) を適切に処理しないため、サービス運用妨害 (DoS) 状態にされる脆弱性が存在します。
[46] Stream-based requests (Request with ReadableStream) (yutakahirano著, ) <https://github.com/whatwg/fetch/commit/0c470b5860fe690b1136b0242951f682405103cc>
chunked_post
If set to 1 use chunked Transfer-Encoding for posts, default is 1.
[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 の挙動でしょうか。
Google Cloud Storage では、HTTP チャンク転送エンコーディングを使用して gsutil ツールまたは boto ライブラリでのストリーミング転送をサポートしています。
[52] Chunked upload Cronet API. - Google グループ () <https://groups.google.com/a/chromium.org/forum/#!topic/net-dev/yvmWG4hexBE>