[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]] などの古い版を使っている人は新しい版にしましょう。) [6] [[HTTP]] と似た仕組みを使う [[SIP]] では、この塊符号化の使用は禁止されています。 [[#comment]] * 仕様書から ** RFC 2616 より、 3.6.1 Chunked Transfer Coding > 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 (おまけ) 実体頭欄を続けることが出来ます。 これにより、動的に生成した内容が、受信者が完全なメッセージを受け取ったか確認するのに必要な情報と共に転送出来るようになります。 [PRE[ Chunked-Body = *chunk last-chunk trailer CRLF ]PRE] [PRE[ chunk = chunk-size [ chunk-extension ] CRLF chunk-data CRLF chunk-size = 1*HEX last-chunk = 1*("0") [ chunk-extension ] CRLF ]PRE] [PRE[ 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) ]PRE] > The chunk-size field is a string of hex digits indicating the size of the chunk[INS[-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[INS[-data]] の長さを[INS[オクテット単位で]]表す 16進数字の文字列です。 chunked (塊)符号化は、長さ 0 の chunk (塊)、それに続く, 空行で終わる trailer (おまけ)で終わります。 [INS[ 訳注: 上記段落での追加部分は Errata (>>8) から補った。 ]INS] > 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 (塊拡張) を無視し'''なければなりません'''。 *** RFC 2068・2616 (HTTP/1.1) 19.4.4; Introduction of Transfer-Encoding > HTTP/1.1 introduces the Transfer-Encoding header field (section [DEL[14.40]] [INS[14.41]]). Proxies/gateways MUST remove any transfer[INS[-]]coding prior to forwarding a message via a MIME-compliant protocol. [17] HTTP/1.1 は Transfer-Encoding 頭欄を導入しました。 串・関門は MIME に従うプロトコルにメッセージを転送する前に [CODE[transfer-coding]] を解か'''なければなりません'''。 > A process for decoding the "chunked" transfer[INS[-]]coding (section 3.6) can be represented in pseudo-code as: [18] "chunked" transfer-coding の復号過程は擬似 code で次のように表せます。 > [PRE[ length := 0 read chunk-size, chunk-ext[INS[ension]] (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 ]PRE] [PRE[ 長さ := 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 から削除 ]PRE] ** RFC の部分の LICENSE See [[RFCのライセンス]] * メモ - [7] >>6 [[RTSP]] も禁止。 [CODE[chunked]] は嫌われ者だねぇ - [8] ''HTTP/1.1 Specification Errata'' - [9] [[Opera]] 6.05 (Win32) の実装をチェックしてみました。 - [10] 改行が CR や LF 単独でも、適当に解釈するので大体意図した通りになります。その辺は人に優しくの精神でいいかげんに実装してある模様。 chunked-extension は対応していないみたいで致命的。引数が表示されて、その字数分あとの計算がずれてきます。これはかなりやばいバグ。 [[TE:]] 欄の申告通り、 Trailer にも対応しています。ただし表示しないことを確認しただけで、本当に機能するかは不明です。 (機能していることを可視化する適当な方法がないんで。) - [11] [[Apache]] は [[CGI]] [[スクリプト]]の出力を可能ならかってに chunked にしてくれます。しかし、 CGI スクリプトが勝手に chunked したデータを吐くのはちゃんと見逃してくれます。 (うっかり二重 chunked なんてことはないようです。) - [12] [WEAK[2003-10-08 07:31:23 +00:00]] ''[[名無しさん]]'': Mozilla は Trailers を正しく無視してくれますが、頭欄としては認識してくれないっぽい。 [19] [CITE[TAKESAKO @ Yet another Cybozu Labs: ニコニコ動画勉強会に行ってきました]] ([TIME[2007-09-10 20:25:31 +09:00]] 版) ([[名無しさん]])