[35] [[HTTP/1.0]] [DFN[[[keep alive]]]] は、[[持続的接続]]を実現する機能です。
[[keep alive]] を使用することは[[接続オプション]] [DFN[[CODE(HTTP)@en[[[keep-alive]]]]]]
によって示されます。 [DFN[[CODE(HTTP)@en[[[Keep-Alive:]]]]]]
[[ヘッダー]]は [[keep alive]] の動作についてのオプションを記述するものです。

* 代替

[36] [[HTTP/1.0]] [[keep alive]] を発展的に置き換えるものが [[HTTP/1.1]]
の標準機能である[[持続的接続]]です。現在では [[HTTP/1.0]] [[keep alive]]
を使う必要はほとんどないものと思われます。

* 仕様書

[REFS[
- [30] '''[CITE@en[RFC 2068 - Hypertext Transfer Protocol -- HTTP/1.1]] ([TIME[2014-09-29 14:21:03 +09:00]] 版) <http://tools.ietf.org/html/rfc2068#section-19.7.1>'''
-- [42] [CITE@en[RFC 2068 - Hypertext Transfer Protocol -- HTTP/1.1]] ([TIME[2014-09-29 14:21:03 +09:00]] 版) <http://tools.ietf.org/html/rfc2068#section-19.7.1.1>
- [18] [CITE@en[RFC 7230 - Hypertext Transfer Protocol (HTTP/1.1): Message Syntax and Routing]] ([TIME[2014-10-21 22:50:09 +09:00]] 版) <https://tools.ietf.org/html/rfc7230#section-6.3>
- [24] [CITE@en[RFC 7230 - Hypertext Transfer Protocol (HTTP/1.1): Message Syntax and Routing]] ([TIME[2014-10-21 22:50:09 +09:00]] 版) <https://tools.ietf.org/html/rfc7230#appendix-A.1.2>
- [62] [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]

* HTTP/1.0 Keep-Alive

[25] [[HTTP/1.1]] では[[持続的接続]]が標準機能となっていますが、
[[HTTP/1.0]] では明示的に示した時のみ有効とできるオプション機能でした。

[26] [[HTTP/1.0]] [[Keep Alive]] に対応したい[[クライアント]]は、
[[要求]]に [CODE(HTTP)@en[[[Connection:]] [[keep-alive]]]]
を含めることができます [SRC[>>24]]。

[31] そのような[[要求]]を受け取った[[鯖]]は、[[応答]]に
[CODE(HTTP)@en[[[Connection:]] [[keep-alive]]]]
を含めることができます [SRC[>>30]]。その場合に[[鯖]]は[[応答]]を送り終わっても[[接続]]を閉じません。
また[[クライアント]]はこれを[[受信]]することで、[[持続的接続]]が有効であると判断できます。

[34] それ以後の[[要求]]と[[応答]]でも、[[接続]]を切断したくなるまでは
[CODE(HTTP)@en[[[Connection:]] [[keep-alive]]]] を含めるようにします。

;; [32] [[HTTP/1.0]] では [CODE(HTTP)@en[[[Transfer-Encoding:]] [[chunked]]]]
を使うことができないので、[[要求]]や[[応答]]の[[メッセージ本体]]の長さは
[CODE(HTTP)@en[[[Content-Length:]]]] [[ヘッダー]]に明示しなければなりません。

[27] しかし [CODE(HTTP)@en[[[Connection:]]]] [[ヘッダー]]に対応していない [[HTTP/1.0]]
[[串]]が [CODE(HTTP)@en[[[Connection:]] [[keep-alive]]]] つきの[[要求]]を受け取ると、 
[CODE(HTTP)@en[[[Connection:]]]]
[[ヘッダー]]をそのまま[[転送]]するので、 [[鯖]]が [[Keep Alive]]
に対応している場合に[[串]]と[[鯖]]の間の[[接続]]が切断されないままとなってしまいます
[SRC[>>24]]。

[28] [[串]]向けには [CODE(HTTP)@en[[[Connection:]]]] [[ヘッダー]]のかわりに
[CODE(HTTP)@en[[[Proxy-Connection:]]]] [[ヘッダー]]を使うことも提案されましたが、
[[串]]が多段になっている時にやはり同様の問題が生じました [SRC[>>24]]。

[29] このような事情から、 [CODE(HTTP)@en[[[Proxy-Connection:]]]]
[[ヘッダー]]は送らないことを、 [CODE(HTTP)@en[[[Connection:]] [[keep-alive]]]]
は注意して使うことが[RUBYB[勧められています]@en[encouraged]]。
[[串]]に対しては使う[RUBYB[べき]@en[ought to]]ではありませんし、
[[鯖]]に対して使う時は[[接続]]が切断されない状態になっていないか監視が必要です。 [SRC[>>24]]

;; [33] [[RFC 2068]] では[[串]]に [CODE(HTTP)@en[[[Connection:]] [[keep-alive]]]]
を送信することは禁止されていました [SRC[>>30]] が、なぜか [[RFC 7230]] では使うべきではないとされる [SRC[>>24]] または[[事実の文]]により除外される [SRC[>>18]] に留まっています。

[52] 一方で [CODE(HTTP)@en[[[NTLM]]]] 認証と [CODE(HTTP)@en[[[CONNECT]]]]
[[要求メソッド]]の組み合わせでの互換性の問題から
[CODE(HTTP)@en[[[Proxy-Connection:]] [[keep-alive]]]] を送信する必要があるようです。
([CODE(HTTP)@en[[[Proxy-Connection:]]]] を参照。)

;; [23] [[持続的接続]]も参照。

* 接続オプション [CODE(HTTP)[keep-alive]]

[19] [[接続オプション]] [DFN[[CODE(HTTP)@en[[[keep-alive]]]]]]
は、[[プロトコルの版]]が [[HTTP/1.0]] である
[[HTTP接続]]において[[持続的接続]]機能を有効にすることを指定するものです。

[22] [[HTTP/1.0]] [[メッセージ]]の [CODE(HTTP)@en[[[Connection:]]]]
[[ヘッダー]]に [CODE(HTTP)@en[[[close]]]] が指定されておらず、
[CODE(HTTP)@en[[[keep-alive]]]] が指定されていれば、
[[受信者]]は[[接続]]を閉じずに次の[[要求]]と[[応答]]の組に当該
[[HTTP接続]]を再利用できます [SRC[>>18]]。

;; [20] [[持続的接続]]を参照。

[21] このオプションは [[HTTP/1.1]] [[接続]]では使えません。 [[HTTP/1.1]]
[[メッセージ]]で指定されていても、無視されます。

;; [[HTTP/1.1]] では既定の状態で[[持続的接続]]が有効です。

* [CODE(HTTP)@en[Keep-Alive:]] ヘッダー

[43] [CODE(HTTP)@en[[[Keep-Alive:]]]] [[ヘッダー]]は、 [[keep alive]]
に関する追加のオプションを指定するものです。

[64] [[HTTP/1.0]] のみで使われます。その他の [[HTTP]] では無視されます。

** 構文

[45] [CODE(HTTP)@en[[[Keep-Alive:]]]] [[ヘッダー]]の値は、
零個以上の[[引数]]の[[リスト]] ([CODE(HTTP)[#]]) です [SRC[>>42]]。

[FIG(railroad)[
= ?
== [[引数]]
== *
=== [[OWS]]
=== [CODE(HTTP)[[[,]]]]
=== [[OWS]]
=== [[引数]]
]FIG]

[46] [[引数]]は、名前と値を [CODE(HTTP)[[[=]]]] で連ねたものです [SRC[>>42]]。
名前は[[字句]]、値は[[字句]]または[[引用文字列]]です。

[FIG(railroad)[
= [[字句]]
= [CODE(HTTP)[[[=]]]]
= |
== [[字句]]
== [[引用文字列]]
]FIG]

;; [47] [CODE(HTTP)[[[=]]]] の前後には [CODE(HTTP)[[[BWS]]]] 
が挿入され得るものと解釈するべきと思われますが、
[[RFC 2068]] 時代は[[空白]]を構文に明示していませんでした。

[57] [[Firefox]] は長らくこれと異なる構文を使っていました (>>54)。

** 文脈

[44] [CODE(HTTP)@en[[[Keep-Alive:]]]] [[ヘッダー]]は、[[要求]]や[[応答]]の
[CODE(HTTP)@en[[[Connection:]]]] [[ヘッダー]]に
[CODE(HTTP)@en[[[keep-alive]]]] [[接続オプション]]が指定されている時に使うことができます
[SRC[>>42]]。

[48] この[[ヘッダー]]は省略可能で、[[引数]]を送る時だけ使います [SRC[>>42]]。

[49] [CODE(HTTP)@en[[[Keep-Alive:]]]] [[ヘッダー]]を送る時は、
[CODE(HTTP)@en[[[Connection:]] [[keep-alive]]]] も送らなければ[['''なりません''']] [SRC[>>42]]。

[65] [[HTTP/2]] では[[生成]]しては[['''なりません''']] [SRC[>>62]]。

** 処理

[50] [CODE(HTTP)@en[[[Connection:]] [[keep-alive]]]] がなければ
[CODE(HTTP)@en[[[Keep-Alive:]]]] [[ヘッダー]]は無視しなければ[['''なりません''']]
[SRC[>>42]]。

[63] [[HTTP/1.0]]/[[HTTP/1.1]] から [[HTTP/2]] に変換する[[中間器]]は、
[CODE(HTTP)@en[[[Connection:]]]] に [CODE(HTTP)@en[[[Keep-Alive]]]]
が明示されているか否かに関わらず、 [CODE(HTTP)@en[[[Keep-Alive:]]]]
[[ヘッダー]]があれば削除する[['''べきです''']] [SRC[>>62]]。

[66] [CODE(HTTP)@en[[[Keep-Alive:]]]] [[ヘッダー]]を含む 
[[HTTP/2]] [[メッセージ]]は[[奇形]]です [SRC[>>62]]。

** 引数

[56] 次の[[引数]]があります。
[FIG(short list)[
- [CODE(HTTP)@en[[[max]]]]
- [CODE(HTTP)@en[[[timeout]]]]
]FIG]

* 歴史

** RFC 2068

[FIG(quote)[
[FIGCAPTION[
[10] RFC 2068 (HTTP/1.1) 19.7.1.1 The Keep-Alive Header
]FIGCAPTION]

> When the Keep-Alive connection-token has been transmitted with a
request or a response, a Keep-Alive header field MAY also be
included. The Keep-Alive header field takes the following form:

[CODE(HTTP)[Keep-Alive]] [CODE(ABNF)[connection-token]]
が要求または応答で転送されるとき、 [CODE(HTTP)[Keep-Alive]]
頭欄をも含めて'''構いません'''。 [CODE(HTTP)[Keep-Alive]]
頭欄は、次の書式を取ります。

>
- Keep-Alive-header = "Keep-Alive" ":" 0# keepalive-param
- keepalive-param = param-name "=" value

> The Keep-Alive header itself is optional, and is used only if a
parameter is being sent. HTTP/1.1 does not define any parameters.

[CODE(HTTP)[Keep-Alive]] 頭自体は省略可能で、引数が送られるときのみ使用します。
HTTP/1.1 は引数を定義しません。

> If the Keep-Alive header is sent, the corresponding connection token
MUST be transmitted. The Keep-Alive header MUST be ignored if
received without the connection token.

[CODE(HTTP)[Keep-Alive]] 頭が送られる場合、対応する接続字句を転送しなければ'''なりません'''。
[CODE(HTTP)[Keep-Alive]] 頭は、接続字句なしで受信した場合には無視しなければ'''なりません'''。
]FIG]

** RFC 2616

[16] [[RFC 2616]] は [CODE(HTTP)@en[[[Keep-Alive:]]]] [[ヘッダー]]を
[[hop-by-hop header]] に分類していました [SRC[>>15]]。

[REFS[
- [15] [CITE@en[RFC 2616 - Hypertext Transfer Protocol -- HTTP/1.1]] ([TIME[2014-09-07 04:14:53 +09:00]] 版) <http://tools.ietf.org/html/rfc2616#section-13.5.1>
- [17] [CITE@en[RFC 2616 - Hypertext Transfer Protocol -- HTTP/1.1]] ([TIME[2014-09-07 04:14:53 +09:00]] 版) <http://tools.ietf.org/html/rfc2616#section-19.6.2>
]REFS]

** RFC 4229

[12] [[RFC 4229]] は [[RFC 2068]] を出典に [[IANA登録簿]]に登録しています [SRC[>>4, >>11]]。

[13] 状態は「[[標準]]」とされています。

;; [14] これは [[RFC 723x]] 出版後も変わっていません。 [TIME[2014-11-04T15:43:59.000Z]]

[REFS[
- [4] [CITE@en[RFC 4229 - HTTP Header Field Registrations]] ([TIME[2014-11-02 09:53:20 +09:00]] 版) <http://tools.ietf.org/html/rfc4229#section-2.1.59>
- [11] [CITE[Message Headers]] ([TIME[2014-10-31 18:26:49 +09:00]] 版) <http://www.iana.org/assignments/message-headers/message-headers.xhtml>
]REFS]

** RFC 7230

[REFS[
- [51] [CITE[#158 (Keep-Alive and Proxy-Connection headers) – httpbis]] ([TIME[2014-11-07 21:52:31 +09:00]] 版) <http://trac.tools.ietf.org/wg/httpbis/trac/ticket/158>
- [55] [CITE@en[RE: more HTTP timeout comments]] ([[Thomson, Martin]] 著, [TIME[2011-03-18 09:05:42 +09:00]] 版) <http://lists.w3.org/Archives/Public/ietf-http-wg/2011JanMar/0241.html>
]REFS]

* 実装

[37] [[Apache]] 2.2 は (標準では?) [CODE(HTTP)@en[[[Connection:]] [[keep-alive]]]]
を送っても無視します。 [TIME[2014-11-07T10:10:02.500Z]]

[40] [[持続的接続]]が有効に設定された [[Apache]] に 
[CODE(HTTP)@en[[[Connection:]] [[keep-alive]]]] 付きの [[HTTP/1.0]] [[要求]]または
[[HTTP/1.1]] [[要求]]を送ると、
[PRE(HTTP code)[
Keep-Alive: timeout=7, max=5
Connection: Keep-Alive
]PRE]
... のような[[ヘッダー]]を含む [[HTTP/1.1]] [[応答]]を送信します。 [TIME[2014-11-07T10:17:51.500Z]]

[41] [[持続的接続]]が有効に設定された [[Apache]] に
[CODE(HTTP)@en[[[Connection:]]]] なしの [[HTTP/1.1]]
[[要求]]を送った時は、 [CODE(HTTP)@en[[[Connection:]]]] や
[CODE(HTTP)@en[[[Keep-Alive:]]]] のない [[HTTP/1.1]] [[応答]]が返されます。[TIME[2014-11-07T10:19:16.00Z]]

[38] [[nginx]] は [[HTTP/1.1]] [[要求]]を送るか [CODE(HTTP)@en[[[Connection:]] [[keep-alive]]]]
付き [[HTTP/1.0]] [[要求]]を送ると、 [CODE(HTTP)@en[[[Connection:]] [[keep-alive]]]]
付き [[HTTP/1.1]] [[応答]]を返し、[[接続]]を閉じません。 [TIME[2014-11-07T10:10:49.300Z]]

[39] [[Chrome]] や [[Firefox]] や [[IE]] は [CODE(HTTP)@en[[[Connection:]] [[keep-alive]]]]
付き [[HTTP/1.1]] [[要求]]を送信します。 [TIME[2014-11-07T10:12:49.300Z]]

[54] 以前は [[Firefox]] も [CODE(HTTP)@en[[[Keep-Alive:]]]] [[ヘッダー]]を送信していましたが、
[[RFC]] とは異なる構文でした。[[鯖]]が使っていなかったことから削除されています [SRC[>>53]]。

[REFS[
- [53] [CITE@en[643352 – Keep-Alive header syntax invalid]] ([TIME[2014-11-07 22:16:43 +09:00]] 版) <https://bugzilla.mozilla.org/show_bug.cgi?id=643352>
]REFS]

* 例

- [1] [SAMP(HTTP)[Keep-Alive: timeout=25, max=85]]
- [2] [CODE(HTTP)[Keep-Alive: 300]]

* 関連

[67] [[TCP keepalive]]と直接の関係はありません。

* メモ

- [3] >>2 は [[Mozilla]], >>3 は [[Apache]]

[5]
[CITE[kinnekoの日記 - IE は KeepAlive をうまく処理できない?]] ([CODE[2007-02-11 10:02:17 +09:00]] 版) <http://d.hatena.ne.jp/kinneko/20051214/p4>
([[名無しさん]])

[6]
[CITE@ja[世界初オタク系SNS『オタバ』公式ブログ: 【Internet Explorer系ブラウザについて】]] ([CODE[2006-10-29 16:47:05 +09:00]] 版) <http://otaba.seesaa.net/article/10637205.html>
([[名無しさん]])

[7]
[CITE[最速インターフェース研究会 :: 最近IE6でWikipedia日本語版の表示が異常に遅いのはKeepAliveのせい]] ([TIME[2007-02-11 10:05:32 +09:00]] 版) <http://la.ma.la/blog/diary_200702101610.htm>

[8] [CITE[Apache HTTP Server Project]]
( ([TIME[2011-05-28 00:58:55 +09:00]] 版))
<http://httpd.apache.org/docs/1.3/misc/known_client_problems.html#broken-keepalive>


[9] [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#appendix-A.1.2>

[58] [CITE@en[draft-thomson-hybi-http-timeout-03 - Hypertext Transfer Protocol (HTTP) Keep-Alive Header]]
( ([TIME[2014-10-16 21:28:37 +09:00]] 版))
<https://tools.ietf.org/html/draft-thomson-hybi-http-timeout-03>

[59] [CITE@en[draft-ietf-http-ses-ext-01 - Persistent HTTP Connections]]
( ([TIME[2014-10-13 07:22:34 +09:00]] 版))
<https://tools.ietf.org/html/draft-ietf-http-ses-ext-01>

[60] [CITE@en[draft-fielding-http-spec-01 - Hypertext Transfer Protocol -- HTTP/1.0]]
( ([TIME[2014-10-18 00:39:13 +09:00]] 版))
<http://tools.ietf.org/html/draft-fielding-http-spec-01#section-4.3.1>

[61] [CITE[RFC Errata Report]]
( ([TIME[2014-12-03 17:38:16 +09:00]] 版))
<http://www.rfc-editor.org/errata_search.php?rfc=4229>