[33] [DFN[[CODE(HTTP)@en[[[Transfer-Encoding:]]]]]] [[ヘッダー]]は、
当該[[メッセージ]]に含まれる[[メッセージ本体]]に適用される(されている)[[転送符号化]]を表すものです。

[15] [[HTTP/1.1]] の [CODE(HTTP)@en[[[chunked]]]] [[符号化]]を使うことを示すために使われます。
[[HTTP/1.0]] や [[HTTP/2]] では使いません。

;; [16] 理論上は [CODE(HTTP)@en[[[chunked]]]] 以外の[[転送符号化]]を指定することもできますが、
実際には使われません。

* 仕様書

[REFS[
- [30] '''[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.3>'''
-- [34] [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.3.1>
- [315] [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-50>
- [316] [CITE@en[RFC 7231 - Hypertext Transfer Protocol (HTTP/1.1): Semantics and Content]] ([TIME[2014-06-07 01:55:45 +09:00]] 版) <https://tools.ietf.org/html/rfc7231#section-4.3.6>
- [1] [CITE@en[RFC 7540 - Hypertext Transfer Protocol Version 2 (HTTP/2)]] ([TIME[2015-05-15 10:14:54 +09:00]] 版) <https://tools.ietf.org/html/rfc7540#section-8.1.2.2>
]REFS]

* 意味

[31] [[要求メッセージ]]は通常[[メッセージ本体]]を持ちませんが、
[CODE(HTTP)@en[[[Transfer-Encoding:]]]] が指定されていれば[[メッセージ本体]]を持ちます
[SRC[>>30]]。

[45] [CODE(HTTP)@en[[[HEAD]]]] [[要求]]に対する[[応答]]や、
[CODE(HTTP)[[[304]]]] [[応答]]は、[[メッセージ本体]]を持たないことになっていますが、
[CODE(HTTP)@en[[[Transfer-Encoding:]]]] 欄は指定しても構いません。
その場合、[[無条件GET]]であったなら[[起源鯖]]が適用するであろう[[転送符号化]]を表します。
[SRC[>>34]]

;; [305] そのような場合に [CODE(HTTP)@en[[[Transfer-Encoding:]]]]
を明示しなければならないわけではありません [SRC[>>34]]。

* 構文

[35] [[欄値]]は、1つ以上の[[転送符号化]]の[[リスト]] ([CODE[#]]) です [SRC[>>34]]。

[FIG(railroad)[
= [[転送符号化]]
= *
== [[OWS]]
== [CODE[,]]
== [[OWS]]
== [[転送符号化]]
]FIG]

;; [314] [[転送符号化]]は、名前の他、[[引数]]が指定されることもあります。
詳しくは[[転送符号化]]の項を参照してください。

[42] これは[[メッセージ本体]]に適用されている[[転送符号化]]を表します。
複数指定されている場合は、元々のデータが前の[[転送符号化]]から順に[[符号化]]されていることを表します。
元のデータを取り出すためには、[[メッセージ本体]]に対して後の[[転送符号化]]から順に[[復号]]していけば良いことになります。

[EG[
[43] 例えば
[PRE(HTTP example code)[
Transfer-Encoding: gzip, chunked
]PRE]
... は、元のデータが [[gzip]] [[圧縮]]されてから、 [[chunked]]
[[符号化]]されていることを表しています。
]EG]

* 文脈

[36] この[[ヘッダー]]は、任意の個数指定できます。

[306] [CODE(HTTP)[[[1xx]]]] [[応答]]、[CODE(HTTP)[[[204]]]] [[応答]]、
[CODE(HTTP)@en[[[CONNECT]]]] [[メソッド]]に対する [CODE(HTTP)[[[2xx]]]]
[[応答]]は、[[メッセージ本体]]を持たないことになっており、
[[鯖]]は
[CODE(HTTP)[[[Transfer-Encoding:]]]] 欄を指定しては[['''なりません''']]。 [SRC[>>34]]

;; [307] なぜか[[鯖]]が主語になっていますが、意図は[[送信者]]かもしれません。

[313] [CODE(HTTP)@en[[[CONNECT]]]] [[メソッド]]に対する [CODE(HTTP)[[[2xx]]]]
[[応答]]は、[[メッセージ本体]]を持たないことになっており、
[[鯖]]は
[CODE(HTTP)[[[Transfer-Encoding:]]]] 欄を指定しては[['''なりません''']] [SRC[>>34, >>316]]。
[[クライアント]]は指定されていても無視しなければ[['''なりません''']] [SRC[>>30 3.3.3., >>316]]。

[308] [[クライアント]]は、[[鯖]]が [[HTTP/1.1]] (以降) に対応していると分かっている場合を除き、
[CODE(HTTP)@en[[[Transfer-Encoding:]]]] [[ヘッダー]]を使った[[要求]]を送信しては[['''なりません''']]。
[SRC[>>34]]

;; [310] [[鯖]]が [[HTTP/1.1]] に対応しているとわかっていても、
[[串]]が対応していないと正しく解釈されないことになります。

;; [18] つまり汎用の[[クライアント]]は[[要求]]で [CODE[Transfer-Encoding:]]
を使えないということになります。前回の[[応答]]で [[HTTP/1.1]] が使われていたと覚えておけば、
使うことができますが...

[309] [[鯖]]は、[[要求]]の[[プロトコルの版]]が [[HTTP/1.1]] (以降) の場合を除き、
[CODE(HTTP)@en[[[Transfer-Encoding:]]]] [[ヘッダー]]を使った[[応答]]を送信しては[['''なりません''']]。
[SRC[>>34]]

;; [19] つまり [[HTTP/0.9]] や [[HTTP/1.0]] では使えません。

[5] [[HTTP/2]] では、[[生成]]しては[['''なりません''']] [SRC[>>1]]。

[312] [CODE(HTTP)@en[[[Content-Length:]]]] [[ヘッダー]]と併用することはできません [SRC[>>30]]。
両方がある時は、 [CODE(HTTP)@en[[[Transfer-Encoding:]]]]
が優先されます [SRC[>>30 3.3.3.]]。[[送信者]]は[[転送]]前に [CODE(HTTP)@en[[[Content-Length:]]]]
を削除しなければ[['''なりません''']] [SRC[>>30 3.3.3.]]。

[3] [[RFC 723x]] には [CODE(HTTP)@en[[[Transfer-Encoding]]]] を 
[CODE(HTTP)@en[[[Connection:]]]] [[ヘッダー]]に指定しなければならないとの規定はなく、
実際にも指定するのは一般的では無いようです。意味的には、
指定するべきようにも思われます。 [[RFC 7540]] は [CODE(HTTP)@en[[[Transfer-Encoding:]]]]
[[ヘッダー]]は [[connection-specific header]] であると述べており [SRC[>>1]]、
暗に [CODE(HTTP)@en[[[Connection:]]]] に示されるべきとの見解を示しています。

;; [4] しかしもし [CODE(HTTP)@en[[[Connection:]]]] に従い
[CODE(HTTP)@en[[[Transfer-Encoding:]]]] を削除し、しかし[[転送符号化]]は無変更で[[転送]]するような[[プロキシ]]があると、
困りそうです。

* 処理

[44] [[串]]や[[関門]]は、[[メッセージ本体]]の[[転送符号化]]を[[復号]]して
[CODE(HTTP)@en[[[Transfer-Encoding:]]]] から削除したり、
[[転送符号化]]を適用して [CODE(HTTP)@en[[[Transfer-Encoding:]]]]
に追加したりしても構いません [SRC[>>34, >>315]]。

[317] [[HTTP/1.0]] [[メッセージ]]に [CODE(HTTP)@en[[[Transfer-Encoding:]]]]
が使われている場合について特に言及はなく、 [[HTTP/1.1]] の場合と変わらず処理するべきと思われます。

[2] [[HTTP/1.0]]/[[HTTP/1.1]] から [[HTTP/2]] に変換する[[中間器]]は、
[CODE(HTTP)@en[[[Connection:]]]] に [CODE(HTTP)@en[[[Transfer-Encoding]]]]
が明示されているか否かに関わらず、 [CODE(HTTP)@en[[[Transfer-Encoding:]]]]
[[ヘッダー]]があれば削除する[['''べきです''']] [SRC[>>1]]。

[8] [[Chrome]] も [[Firefox]] も [[IE]] も、未対応の[[転送符号化]]だけが指定されていると、
無視するようです。 [TIME[2015-08-04T14:30:54.600Z]]

[9] [[Chrome]] と [[Firefox]] は、 [CODE(HTTP)@en[[[chunked]]]] が指定されていると、
それ以外が前後どちらに指定されていても、 [CODE(HTTP)@en[[[chunked]]]] として処理するようです。
[CODE(HTTP)@en[[[chunked]]]] が複数指定されていても一度の指定とみなすようです。 [TIME[2015-08-04T14:34:12.700Z]]

[13] [[IE]] は [CODE(HTTP)@en[[[chunked]]]] と未対応の[[転送符号化]]の両方が指定されていると、
無視する ([[転送符号化]]なしとみなす) ようです。 [TIME[2015-08-08T06:57:19.600Z]]

[14] [[Chrome]] や [[Firefox]] や [[IE]] は、 [CODE(HTTP)@en[[[Transfer-Encoding:]] [[chunked]]]]
があれば、 [CODE(HTTP)@en[[[Content-Length:]]]] は無視されます。
[CODE(HTTP)@en[[[Content-Length:]]]] のエラーチェックもされないようです。
[TIME[2015-08-08T07:00:50.600Z]]

[6] [[HTTP/2]] では、 [CODE(HTTP)@en[[[Transfer-Encoding:]]]] が含まれる[[メッセージ]]は[[奇形]]です [SRC[>>1]]。

[17] 実際には [[Firefox]] は無視するだけのようです。 [[Chrome]]
は[[奇形]]とみなします。 [TIME[2015-10-11T09:40:52.600Z]]

* 転送符号化の一覧

[38] [[転送符号化]]の種類とその名前については、[[転送符号化]]を参照してください。

[39] [CODE(HTTP)@en[[[chunked]]]] は特別な[[転送符号化]]です。 [[HTTP/1.1]]
では実装が義務付けられていますし、他とは異なる要件も課されています。

;; [CODE(HTTP)@en[[[chunked]]]] の項を参照してください。

[311] [CODE(HTTP)@en[[[chunked]]]] [[転送符号化]]以外の[[転送符号化]]を用いるときは、
最終的に [CODE(HTTP)@en[[[chunked]]]] [[転送符号化]]も適用するか、
または[[接続]]を閉じることによって[[メッセージ]]を終端させるかのいずれかとしなければ[['''なりません''']]
[SRC[>>34]]。

* 歴史

[FIG(quote)[
[FIGCAPTION[
[32] RFC 2068 (HTTP/1.1) 14.40; RFC 2616 (HTTP/1.1) 14.41 Transfer-Encoding
]FIGCAPTION]

> The Transfer-Encoding general-header field indicates what (if any)
type of transformation has been applied to the message body in order
to safely transfer it between the sender and the recipient. This
differs from the [DEL[Content-Encoding]] [INS[content-coding]] in that the transfer[INS[-]]coding is a
property of the message, not of the entity.

[CODE(HTTP)[Transfer-Encoding]] [[一般頭欄]]は、
[[メッセージ本体]]を送信者と受信者の間で安全に転送するために変形が適用されているなら、どの型の変形が適用されているのかを示します。
[CODE(ABNF)[[[transfer-coding]]]] はメッセージの特性であって実体の特性ではないという点で
[CODE(ABNF)[[[content-coding]]]] とは異なります。

>
- Transfer-Encoding       = "Transfer-Encoding" ":" 1#transfer-coding

> Transfer[INS[-]]codings are defined in section 3.6. An example is:
- Transfer-Encoding: chunked

[INS[

> If multiple encodings have been applied to an entity, the transfer-codings MUST be listed in the order in which they were applied.
Additional information about the encoding parameters MAY be provided
by other entity-header fields not defined by this specification.

一つの[[実体]]に複数の符号化が適用されているのなら、
[CODE(ABNF)[transfer-coding]] は適用された順に列挙しなければ'''なりません'''。
符号化引数についての追加の情報をこの仕様書で定義しない他の[[実体頭欄]]で提供しても'''構いません'''。
]INS]

> Many older HTTP/1.0 applications do not understand the Transfer-Encoding header.

多くの古い [[HTTP/1.0]] 応用は、 [CODE(HTTP)[Transfer-Encoding]] 頭を理解しません。


** RFC 2068・RFC 2616 (HTTP/1.1) 3.6 Transfer Codings

→[CODE(WikiPage)[[[転送符号化//HTTP]]]]


** RFC 2068・2616 (HTTP/1.1) 19.4.4; Introduction of Transfer-Encoding

→[CODE(WikiPage)[[[chunked]]]]
]FIG]

* 実装

[26] [[Opera]] 6.05 (Win32) は [CODE(HTTP)[TE: deflate, gzip, chunked, identity, trailers]] を送ってきます。実際ちゃんと対応しています。 [CODE(HTTP)[Transfer-Encoding: x-gzip]] みたいな値でも解釈してくれます。

[27] >>26 複数の値を指定しても OK です。 [CODE(HTTP)[gzip,deflate]] とか [CODE(HTTP)[gzip,chunked]] みたいに。[CODE(HTTP)[chunked,gzip]] (不正) も解してくれますが、 [CODE(HTTP)[chunked,gzip,chunked]](不正)や [CODE(HTTP)[chunked,chunked]] だと内側の chunked が解されずに残ります。

[28] 手元の [[WinIE]] 3.02, [[NC]] 4.01, [[w3m]] 0.3.2.2 はいずれも転送符号化に対応していません。

[29] >>26,28 知らない転送符号化・内容符号化は知らんふりして処理を続行させようとするみたいです。

* 関連

[37] [CODE(HTTP)@en[[[Transfer-Encoding:]]]] は [CODE(MIME)@en[[[Content-Transfer-Encoding:]]]]
と似ていますが、 [[CTE]] が[[8ビット安全]]でない[[輸送路]]に任意のデータを通すためのものなので、
元々[[8ビット安全]]である [[HTTP]] の [CODE(HTTP)@en[[[Transfer-Encoding:]]]]
とは目的が違っています [SRC[>>34]]。

[40] [CODE(HTTP)@en[[[Transfer-Encoding:]]]] は[[メッセージ]]の特性であり、
[CODE(HTTP)@en[[[Content-Encoding:]]]] は[[表現]]の特性であるとされています。 [SRC[>>34]]
[[転送符号化]]は[[中間器]]が適宜復号したり、符号化したりして構わないことになっていますが、
[[内容符号化]]は[[中間器]]が変更してはなりません。

[EG[
[41] [[圧縮]]されたデータを転送したい時には[[内容符号化]]を使い、
データを効率的に転送するために[[圧縮]]したい時には[[転送符号化]]を使うのが意図に沿った用法です。
]EG]

* メモ

[21] HTTP には転送符号化と[[内容符号化]]という似た二つの概念があります。

前者は転送を安全に行うための手段であって [[chunked]] 符号化が現在実質的に唯一使えます。
Transfer-Encoding: 欄の他に [[TE]] 欄が関係します。

後者はその名の通り内容の符号化ですが、現時点では実質的に[[圧縮]]転送のための手段となっています。

[22] HTTP から派生したプロトコルである [[RTSP]] や [[SIP]]
では chunked 符号化を禁止するなど差異がありますので注意が必要です。

[23] [[CGI]] で[[転送符号化]]した内容を出力するのって機能するんでしょうか?
仕様書には特に触れられていませんね。

サーバーが [[Apache]] でクライアントが [[HTTP/1.1]] の場合は、 CGI
や [[SSI]] などを使うと chunked 符号化をサーバー側が処理するみたいですが・・・。

[FIG(quote)[
[FIGCAPTION[
[7] [CITE@en[Re: ''''''[''''''Technical Errata Reported'''''']'''''' RFC7230 (4412)]]
([[Zhong Yu]] 著, [TIME[2015-07-10 03:33:46 +09:00]] 版)
<https://lists.w3.org/Archives/Public/ietf-http-wg/2015JulSep/0042.html>
]FIGCAPTION]

> Transfer-Encoding: gzip
> Connection: close
> I tested this response with five major browsers. All of them seem to know
> to consume the response body till connection EOF. ( None of them knows how
> to deal with the 'gzip' encoding; and if EOF arrives prematurely resulting
> in a corrupted  'gzip' body, none of them detects it as a problem. )
> 

]FIG]


[10] [CITE[Issue 94730 - chromium - RFC2616 "Transfer-Encoding: gzip, chunked" not handled properly - An open-source project to help move the web forward. - Google Project Hosting]]
([TIME[2015-08-05 00:07:26 +09:00]] 版)
<https://code.google.com/p/chromium/issues/detail?id=94730>

[11] [CITE@en[68517 – RFE: Improved support for HTTP/1.1 transfer codings (transfer-encoding)]]
([TIME[2015-08-05 00:08:40 +09:00]] 版)
<https://bugzilla.mozilla.org/show_bug.cgi?id=68517>

[12] [CITE@en[59464 – Any Transfer-Encoding header is interpreted as "chunked"]]
([TIME[2015-08-05 00:13:38 +09:00]] 版)
<https://bugzilla.mozilla.org/show_bug.cgi?id=59464>