HTTP接続

接続 (HTTP)

[535] HTTP 通信の直接の当事者間の仮想回路を、 接続 (connection) といいます。

[564] 接続の両端はクライアントですが、が介在する場合、 一方又は両方がとなることもあります。

仕様書

状態

[46] 接続 (connection) は、2つのエンドポイントの間のトランスポート層接続です >>45

[50] 接続エンドポイントは、クライアントサーバーかのいずれかです。

[48] HTTP/0.9HTTP/1.0HTTP/1.1HTTP/2 >>47接続は、 TCP接続上で動作するアプリケーション層プロトコル輸送路です。

[49] TLS が間に挟まることもあります。 TCP の代わりにプロキシプロトコルを用いる場合もあります。 (>>516)

[204] 利用者エージェントは、 接続プールとして接続群を保持します >>203

[205] 接続は、起源credentialsの組で識別されます >>203

[119] エンドポイントは、接続ごとに次の状態を持ちます。

起源
起源オブジェクト >>203
credentials
真偽値 >>203
下位層の情報
自身と peerホスト名IPアドレスポート番号TLSセッションRTT など。
プロトコルの版
HTTP/0.9HTTP/1.0HTTP/1.1HTTP/2 のいずれか。
自身のHTTP設定
自身が値を決定した HTTP/2 設定の各引数の値です。
peerHTTP設定
peer から値を受信した HTTP/2 設定の各引数の値です。
HTTPストリーム
HTTP/2接続内にある0個以上HTTPストリームの情報です。 初期状態では、空です (が Upgrade: h2c でははじめにストリームが作られます)。
HPACK 符号化用動的表
HTTP/2 ヘッダーブロックの生成に使う動的表です。
HPACK 復号用動的表
HTTP/2 ヘッダーブロックの解釈に使う動的表です。
依存性木
HTTP/2 ストリーム優先度を表すです。
GOAWAY 送信最大ストリームID
GOAWAY を送信した場合その最大ストリームID。それより大きなストリームは以後処理しない。
GOAWAY 受信最大ストリームID
GOAWAY を受信した場合その最大ストリームID
タイムスタンプ
タイムアウトによる切断のために必要な情報。開始時刻、最後の送受信時刻など。
SETTINGS タイムスタンプ
自身が最後に送信し、まだ ACK を受信していない SETTINGS フレームの送信時刻です。一定時間経過後、タイムアウトによるエラーとなります。
GOAWAY 送信時刻
GOAWAY を送信した場合そのタイムスタンプ。
接続フロー制御窓
HTTP/1.1 以下の状態
HTTP接続の処理を参照。

[217] WebSocket接続は、更に WebSocket 固有の状態を持ちます。

WebSocket接続の項を参照。

HTTP の版

[566] 接続がどのように処理されるかは、HTTPの版によって異なっています。 HTTPの版は、 HTTP/1.1 以下HTTP/2 のいずれであるかは TLSALPN により示され、更に HTTP/1.1 以下の場合には接続上を流れるHTTPメッセージ先頭行でそのいずれであるかが示されます。

ALPNh2
HTTP/2
ALPNhttp/1.1 または ALPN なし
先頭行HTTP/1.1
HTTP/1.1
それ以外で先頭行プロトコルの版
HTTP/1.0
それ以外
HTTP/0.9
それ以外
HTTP

[10] HTTP/1.1 以下の場合、理論上は要求ごと、 あるいは応答ごとに異なるプロトコルの版を記述することもできますが、 普通はそのようなことはありません。 そのような状況で受信者がどう処理するべきかは不明です。

[136] 実際の Webブラウザーは、 HTTP/1.1HTTP/1.0HTTP/0.9 が同じ接続内に混在しても、それぞれの動作に従い処理します。 1xx最後の応答プロトコルの版が異なっていても構いません。

[137] HTTPの構文解析状態行HTTP/0.91xx を参照。なお、一部ブラウザーで例外的にエラーとなることがあります (各項参照)。

[11] がおかしなメッセージを返したことによって HTTP/1.1HTTP/1.0接続の途中で HTTP/0.9 メッセージが出現したと判断し、おかしな動作をする Webブラウザーもありました。セキュリティー上の問題となる可能性もありますから、 注意が必要です。

[118] 途中で版が変わる場合にはエラー応答を返したり、接続を切断したりするべきなのかもしれません。 なおプロキシは受信したメッセージをそのまま転送するのではなく、 自身の対応する適切な版を選択して適宜書き換えて転送することが期待されていますから、 プロキシとの通信であっても途中で版が変わることはないはずです。

[54] HTTPの版の決定方法については、プロトコルの版を参照してください。

[78] HTTP/2 から HTTP/1.1 への切り替えもあります (>>79)。

接続を得る

[206] 利用者エージェントクライアント起源起源boolean credentialsboolean 事前 (既定値は) について接続を得る (obtain a connection) には、 次のようにします >>203

  1. [207] クライアント接続プールに、 起源起源credentialscredentials接続があれば、
    1. [208] それを返し、ここで停止します。
  2. [209] 接続を、起源への HTTP接続を確立した結果に設定します。 credentialsなら、TLSクライアント証明書を送信しません。 本 fetchterminate されたら、接続を中断します。
  3. [289]fetchterminate されている場合、
    1. [290] 接続null 以外の場合、
      1. [291] 接続を閉じます。
      2. [292] 失敗を返し、ここで停止します。
  4. [210] 接続失敗なら、
    1. [211] 失敗を返し、ここで停止します。
  5. [212] 接続起源を、起源に設定します。
  6. [213] 接続credentialsを、credentialsに設定します。
  7. [214] 接続を、クライアント接続プールに追加します。
  8. [215] 接続を返します。

[231] 事前の場合、HTTP接続の確立 (>>209) はできれば完全に行うべきですが、 資源制約その他の理由で叶わなければ、 一部または全部を省略して構いません >>230

[232] 例えば DNS名前解決のみとしたり、 TCP までで TLS は行わなかったりしても構いません。 >>230

[233] もちろん、その事前接続を後から実際に利用するためには、 接続の確立の処理を完了させる必要があります。

[219] 後述の通り、同じサーバーに複数の接続を同時に確立できます。 接続プールには、起源credentialsの組が同じ接続が複数含まれているかもしれません。 何個まで含められるかや、それらからどうやって選ぶか(選ばないか)は、 クライアントに委ねられています。 (パフォーマンスや利用可能資源などのトレードオフを考慮する必要があります。) 事前なら、 既に十分な数の接続があれば、新たな接続を確立しないことにするかもしれません。 事前なら、接続数が減少するまでHTTP接続の確立の実処理を遅延させる必要がありそうです。

[216] WebSocket接続を得る手順は、これとは別に用意されています (詳細はそちらの項を参照)。 通常のHTTP接続を得る手順とおおむね同趣旨ではあるのですが、 WebSocket は必ず新しい接続を使うので、接続プールは参照しません。 (これは事前接続が利用されないことも意味します。)

[218] これらは、 HTTP-network fetch から呼び出されます。

[224] 接続を得るは、事前接続の開始からも呼び出されます。

接続先の決定

[531] 接続先のは、他のインターネットアプリケーション層プロトコルと同じように、 URL などによって指定されたドメイン名IPアドレスなどとポート番号とを使って識別されます。

[532] http: の項も参照してください。

[67] URL schemehttp: なら TCP を、 https: なら TLS over TCP を下位層として使います。

[68] HSTS では特定の条件を満たす http: URL に接続する前に https: URL へと書き換えます。 この処理は fetch で行われます。 HTTP接続の確立の段階では、 既に書き換え済みです。

[197] クライアント代替サービスに対応しており、接続先の URL schemeホストポートの組に対して適用可能な代替サービスを知っている場合、 接続先のプロトコルホストポートをその代替サービスのものとします。

詳細は代替サービス参照。

[199] Chrome は、 QUIC が利用可能なら、そちらに切り替えます。

[285] Firefox は、 Opportunistic HTTP/2 Security が利用可能なら、 そちらに切り替えます。

[533] プロキシは、利用者エージェントの設定などの実装依存の方法で指定されます。 が指定されている場合は、接続先はサーバーではなく、プロキシとなります。

[534] 多くのWebブラウザーは、 proxy.pac による指定に対応しています。
[198] 代替サービスに接続する場合も、必要に応じてプロキシを使います。

[19] 名前解決を委ねる場合を除き、通常はホスト部の名前解決を行い、 IPアドレスを取得し、それを接続先のとします。名前解決DNS によって行うのが基本ですが、 /etc/hostsNetBIOS など当該システムが実装している他の名前解決の仕組みが用いられることもあります。

名前解決を参照。
インターネットDNS による名前解決localhost、 それに IPアドレスによる直接指定を除くと、 システム依存の名前解決方式に依存した接続先の指定は相互運用不能です。

接続の開始

[530] 接続は、クライアント (または) に対して下位層プロトコルの接続を確立することにより、開始されます。 は下位層プロトコルと OS 等の API (ソケットなど) の規定に基づき予め接続を受け付ける状態で待っている必要があります。

[69] 下位層プロトコルの章 (>>516) も参照。

[536] HTTP/1.1 以下では、他の多くのアプリケーション層プロトコルとは違って、 接続の初期化のようなプロトコル上の手続きはなく、すぐに要求を送信できます。

[70] HTTP認証は、接続レベルではなく、個々の要求のレベルで行われるのが原則です。 (HTTP認証の項を参照。) 従って、 HTTP レベルでは接続の確立の段階で challengecredentials の送信など認証操作は行われません。 もちろん、サーバーは必要なら下位層の接続が確立された (確立しようとする) 時点で IPアドレスTLSクライアント証明書などを使って HTTP よりも前に認証を行うことはできます。

[568] 接続が確立されると、クライアント要求を送信します。 その送信のタイミングは特に規定されていませんが、通常は即座に送信します。 後述の通り、は通常タイムアウトを設定しており、一定時間内に要求が送信されなければ、 エラーとして扱います。

[20] クライアント名前解決に失敗した場合や下位層プロトコルの接続の確立に失敗した場合は、 当然ながら HTTP接続を利用することはできず、要求を送信できません。

cross-protocol attack

[121] HTTP/1.1 以下は単純なテキストベースのプロトコルなので、 攻撃者の指示によりクライアントが他のプロトコルに接続できる文字列を送ることができる場合があります。

[114] multipart/form-data によりフォームデータHTTP で送信することで、 cross-protocol attack が試みられることがあります。
[122] HTTPヘッダーなど他のプロトコルで解釈できない部分を未知の命令などとして無視するプロトコルを攻撃できます。

[113] Webブラウザーport blocking により他のプロトコルが使うことが多いポートへのアクセスを拒み、 cross-protocol attack を難しくしています。

[110] HTTP/2 over TLSALPN によりプロトコルを明示でき、 また暗号化のため TCP 上のバイト列を制御することが難しいため、 cross-protocol attack は困難です >>111

[123] HTTP/1.1 以下 over TLS暗号化のため、平文プロトコルを攻撃することは困難です。 しかし ALPN を使わなくて良いため、 TLS 上の非 HTTP プロトコルは攻撃できるかもしれません。

[112] HTTP/2 over TCP接続序文により HTTP/1.1 以下の実装の誤動作を防ごうとしていますが、 非 HTTP プロトコルに対する cross-protocol attack を防ぐものではありません >>111

接続の並行性

[87] HTTP/1.1 以下では、1つの接続で同時に送受信できる応答は1つだけです。 1つの文書に埋め込まれた複数の画像が存在する場合など、 クライアント側の処理性能の向上のためには複数の接続並列に確立する必要があります。

[88] HTTP/1.0keep-aliveHTTP/1.1持続的接続パイプライン化を用いると 1つの接続を再利用して次の応答を受信することができ、 TCP接続の再確立や次の要求の送受信の時間を節約できますが、 前の応答が完了するまで次の応答は送信できませんから、 すぐにレンダリング開始したいなら、やはり複数の接続が必要となります。

[89] しかし接続数が多すぎるとサーバーネットワークに過剰な負荷を与えてしまう虞があるため、 クライアントは適当な上限を設けるべきです。

[550] 旧仕様の RFC 2616 までは、あるクライアントからある (や) への同時接続数は2以下とするべきだとされていました >>549

[551] RFC 7230 は、応用によっては非現実的なので、特定の上限は設けないが、 クライアント接続を開くのには保守的であるようにと求めています >>548

[552] 多くの Webブラウザーは、00年代前半までは RFC の上限を既定値とし、 設定によっては更に増やすこともできるようになっていました。 しかしその後 Ajax の普及などに伴い徐々に制限が緩和されています。

[91] HTTP/2 では持続的接続が基本動作となっており、 クライアントは必要が無いと判断するまで接続を閉じずにいることが期待されています >>90クライアントは 1つの接続で複数のストリームを使って並行して応答を受信できます。 クライアントは、プロキシを含むサーバーへの接続を、 ホストポートの組に対して複数開くべきではありません >>90

[116] これはサーバー利用者の動作を追跡しやすくすることになり、 注意が必要です。 >>115

[93] HTTP/2 クライアントは、異なる値を SNI に指定する場合や異なる TLS クライアント証明書を指定する場合は、同じ IPアドレスTCPポートに対して複数の接続を開いて構いません。 しかし同じ指定で複数の接続を開くことは避けるべきです>>90

[103] 逆に複数のホストが同じ接続を共有する場合 (>>96) があります。

[92] HTTP/2 クライアントは、既存の接続ストリーム識別子空間を使い果たしつつある場合や、 TLSセッションの鍵の更新のため必要な場合、 エラーを検出した場合には、代替となる接続を新たに開くことができます >>90

他の接続を待つ

[237] WebSocket に関しては、他の接続が閉じられるのを待つ処理が明文化されています。

[236] 他の接続を待つ場合は、次のようにしなければなりません >>234

  1. ホストから、 IPアドレスを得ます (名前解決)。
  2. ホストからIPアドレスを得られない場合 (例えば名前解決プロキシに委ねている場合)、
    1. host を、ホストに設定します。
    2. n を、十分小さな値とするべきです。例えば開いているタブ数を考慮して決めます。
  3. それ以外の場合、
    1. host を、IPアドレスに設定します。
    2. n を、1 に設定します。
  4. 同じ hostポートへの状態が CONNECTING であるWebSocket接続があるか調べます。
  5. その数が n 未満となるまで、待ちます。

[238] この制限は、著者が多数の WebSocket接続を開いて DoS攻撃することを難しくするためのものです >>234

[239] ホストのみで制限する実装とホストポートの組で制限する実装があります >>235
[240] これをうまく使うとあるホストとあるホストが同じ IPアドレスかどうかをある程度の精度で推測できるかもしれませんが、 それによって何か問題になることはあまり無さそうです。

[241] HTTP/1 (非 WebSocket) と HTTP/2 に関しては明文規定はありませんが、 n 以外は同様に処理するべきものと思われます。 (プロキシへの接続と起源サーバーへの接続とでも n は違いそうです。)

接続の再利用

[94] HTTP/1.0 keep-aliveHTTP/1.1 持続的接続HTTP/2 では、同じ接続を複数の要求応答の組の送受信に再利用できます。

[95] HTTP/1.0HTTP/1.1 でどのような場合に接続を再利用できるのかは、 明確な規定がありません。

[96] HTTP/2起源サーバーへの接続は、直接のものであれ CONNECT トンネル経由であれ、 authority が異なっていても当該起源サーバーauthoritative である限り、再利用できます。 >>90

[97] 具体的には、 TLS 無しの TCP では、ホストが同じ IPアドレス解決されることをいいます。 >>90, >>108, >>109 (もちろんポート番号も一致する必要があります。)

[98] https では、 TCP のみの場合の条件に加え、 サーバー証明書が新しい TLS接続の場合と同様の検査を満足しなければなりません>>90, >>108, >>109

[99] SANワイルドカード証明書を使うと、同じ証明書で複数の authority に対応できます。
[102] 複数のホストへ同じ接続を利用できる本規定と、 同時接続の禁止 (>>91) がどう関係するのかは不明です。
[117] 起源を超えてサーバー利用者の行動を追跡しやすくなりますから、 注意が必要です >>115

[104] サーバーの構成によっては、 SNI で指定されたホストによって中間器が異なる起源サーバーを選択する場合など、 クライアントが (機密かもしれない) 要求を誤ったサーバーに送ってしまう可能性もあります。 サーバーは、クライアント接続を再利用してほしくない場合、 authoritative でないことを 421 応答によって表明できます。 >>90

[105] クライアントは事前に判定できないので、要求が他者に漏洩してしまう可能性があるわけですが、 良いのでしょうか... クラウドサービスの共通の逆串などで証明書まで共有していても異なる起源サーバーに接続されることはあるでしょうから、その場合クラウドサービス提供者は確実に 421 応答を返すよう注意が必要です。

[106] HTTP/2 プロキシを使うクライアントは、 すべての要求を同じ接続に送信します >>90

[185] 要求URLも参照。

[283] 代替サービスに関してはまた別の要件があります。

接続上を流れるもの

[401] 通常の HTTP の通信では、HTTPメッセージ接続上を送受信されます。

[523] HTTPメッセージは、要求メッセージまたは応答メッセージです。 現在の HTTP ではクライアントからへと送信されるのが要求からクライアントへ送信されるのが応答と決まっています。

[52] テキスト形式プロトコルである HTTP/1.1 以下では、 メッセージRFC 822 風のテキスト形式で表現され、 接続上を直接送受信されます。

[53] バイナリー形式プロトコルである HTTP/2 では、 メッセージは複数のフレームの列で表現され、 接続内のストリーム上のバイト列として送受信されます。

HTTP/1.1 以下

[55] 要求クライアントからサーバーへと送信し、 それに対して応答サーバーからクライアントへと送信するのが基本的な動作です。 接続を開き、送受信を行ってから、接続を閉じます。

C
クライアント
S
C ## S
接続の確立
C -> S
要求
S -> C
応答
C ## S
接続を閉じる

[522] 持続的接続機能を使うと、1つの接続で複数の要求応答の組をやりとりすることができます。

[9] 持続的接続HTTP/1.1 では標準機能となっています。 (HTTP/1.0 では Keep-Alive は実験的に追加された機能でした。) 詳しくは持続的接続を参照。

[513] 要求応答の対応関係は、明示されません。 要求が送信されたのと同じ順に応答が送信されます。 >>512

[524] ですから、下位層プロトコルは順序を保証するものである必要があります。

[525] 応答は、必ず要求に対する反応として送信されます。 要求がないのに応答が送信されることは、原則としてありません。

[526] 例外的に、接続をはじめてから何も送られないままタイムアウトした場合など、 特別に応答が送信され、ただちに接続が閉じられるケースがあります。

[528] メッセージの境界は、メッセージ自体によって、または接続が閉じられることにより識別されます。下位層プロトコルはオクテット列の送受信のみが要求されています。

[529] 詳しくはメッセージメッセージ本体の項を参照してください。

[132] は、少なくても1つは要求行の前の CRLF を無視するべきです >>131。 実際には他の改行と同じく、省略可能な CR とその後の LF が無視されるようです。

[133] Apachenginx も、要求の前の任意の個数の改行を無視するようです。

[134] すべての実装がそのように動作するなら、 ping の代用とできるかもしれません。 実際どうなのかは定かではありません。

[546] パイプライン化により、要求に対する応答の到着を待たずに次の要求を送ることもできます。

詳しくはHTTPパイプラインの項を参照してください。

[402] CONNECT メソッドに対して 2xx 応答が返された場合、メッセージはそこで終端され、 以後はトンネルとなります。詳しくは CONNECT の項を参照してください。

[562] Upgrade: によってプロトコルが切り替えられる場合、 によって 101 が返され、それよりも後は新しいプロトコルに切り替わります。 詳しくは Upgrade:WebSocket接続の確立WebSocket接続の項を参照してください。

[38] パイプライン化CONNECTUpgrade: の組み合わせは思わぬ副作用を生むかもしれません。例えば別のプロトコルに切り替わる前にクライアントがデータを送信していると、 がそれをどう解釈するかが曖昧となり、セキュリティー相互運用性の問題を引き起こすことがあります。 RFC 7472HTTPS の歴史の項も参照。
[43] クライアントが対応していない 101 応答を受信した場合のクライアントの処理は、101 を参照してください。

応答間のデータ

[167] 前の応答を受信し終えてから次の要求の送信を始めるまでの間に受信したデータは、 どのブラウザーも捨てるようです。

[168] それに対して HTTP ではどのブラウザーも最初の要求の送信前に受信した (であろう) データは最初の要求への応答とみなすようです。

[169] HTTPS では ChromeIE は (TLS handshake 後に送られた) 最初の要求の送信前にデータを受信したら、最初の要求ネットワークエラーとするようです。

[171] FirefoxHTTPS で最初の要求の前に受信しても最初の応答とみなすように見えます。 しかし応答後に受信したデータがあると次の要求にその接続を使わないように見えます。 (Chrome では HTTP と同じく応答後のデータは無視するように見えます。)

[265] nginxApache は最初の要求の前に LF または CRLF があれば、これを無視します。 それ以外の CR と LF の列があると、 nginx はおかしな状態になり、 Apache要求行として解釈しようとしてエラーを返します。

[266] nginx は最初の要求と次の要求の間で任意の CR と LF の列を無視します。 Apache は LF または CRLF の任意個の繰り返しを無視します。

[170] いずれの場合についてもネットワークTCP/IPスタックの状況によってアプリケーションに到達するタイミングが左右される上、 接続の確立から最初の要求を送信するまでの時間はごくわずかなので、 動作は不確かです。

HTTP/2

[80] ストリームの処理については、ストリームフレームを参照。

[81] メッセージの送受信については、HTTPメッセージHTTP要求HTTP応答サーバープッシュを参照。

[51]エンドポイントは、メッセージを構成するフレームの他、 適宜 PING フレームフロー制御のための WINDOW_UPDATE フレーム設定変更のための SETTINGS フレームなどを送受信することになります。

[57] HTTP/2 CONNECT 要求メソッドは、 ストリーム内のデータの送受信をトンネルとして使います。 HTTP/1.1 とは違って接続全体が切り替わるのではないので、他のストリームにより (または同じストリームDATA 以外のフレーム型により) HTTP データの送受信は継続できます。
[58] HTTP/2 では Upgrade: は使えません。

最初の要求と応答

[284] Opportunistic Security for HTTP/2 では、 実際の要求応答の送受信の前に、 /.well-known/http-opportunistic の送受信が発生します。 ただし、HTTPキャッシュにより省略される場合もあります。

要求の時機

[225] 基本的には、接続が確立されたら、すぐに最初の要求が送信されます。

[226] 事前接続を用いる場合は、接続の確立から最初の要求の送信までに若干の時間があるかもしれません。

[228] 同じ接続を再利用 (>>94) して次の要求を送信する場合もあります。 これも前の要求応答の後すぐに送信される場合もあれば、時間を置く場合もあります。

[229] HTTP/1 では理論上 HTTPパイプラインにより前の応答を待たずに次の要求を送ることができますが、 実際には不可能です。 HTTP/2 では複数のストリームを同時に用いられるので、 他の要求応答のタイミングに関わらず次の要求を送信できます。

[227] サーバーは、一定時間内に要求が送信されなければ、 タイムアウト (>>554) で接続を閉じるかもしれません。

応答の時機

[569] 応答が送信されるタイミングは、特に規定されていません。 要求の末尾まで読み終えるよりも先に送信される可能性もありますし、 要求がすべて読み終わってからしばらく経ってようやく送信される可能性もあります。 要求が送信され始めるより前に応答が返されることもあるかもしれません。 long poll では、応答の送信開始や送信完了までの待機時間が長いかもしれません。

[579] 要求非妥当である場合や、要求要求行ヘッダー、 あるいはメッセージ本体の途中でが処理できないと判断した場合、 要求をすべて読み終わる前やクライアント要求を送信し終わる前にがエラー (400413505 など) を返したり、 接続を閉じたりすることがあります。

[44] クライアントは通常タイムアウトを設定しており、一定時間内に応答の一部または全部が返されなければ、 通信やサーバーのエラーとみなします。タイムアウトまでの時間は、アプリケーションの性質やサーバークライアントの用途、 想定されるネットワークの状態など様々な因子に依存するため、一概には決められません。

[572] メッセージを構成するデータの送信速度は、一様でなくても構いません。 例えば、multipart/x-mixed-replace 応答を返す場合、 ある程度の時間をあけて複数の本体部分を送信し続けることになります。

もちろん、実装によってはタイムアウトがありますから、 あまりにも長時間データの送信が行われないと、エラーとみなして接続が閉じられることがあります。

[573] 用途によっては、 payload body が無限に長いこともあります。 その場合は、相手側によって接続が閉じられたり、 ネットワークエラーなど外部的な要因で接続が閉じられたりしない限り、 データの送信が継続されます。

[574] ですから、 HTTP の実装は、メッセージが有限の長さを持つことを仮定することはできません。

1xx 応答

[514] 1xx 応答が最終応答より前に送信される場合には、 1つの要求に複数の応答が対応することとなります。 >>512

C
クライアント
S
C -> S
要求
S -> C
1xx 応答
S -> C
1xx 応答
S -> C
最後の応答
[527] 要求送信後に接続が閉じられた場合など例外的なケースを除けば、 要求には必ず応答が送られます。

[56] 1xx 応答は、 HTTP/1.1 以上の場合に、 最後の応答の前に0個以上使うことができます。

  1. *
    1. 1xx 応答
  2. 最後の応答
[162] 101 の後 WebSocket に切り替わる場合は、 最後の応答はありません。

[570] 要求100-continue が指定されている場合には、 要求ヘッダー部を読み終えた時点で100 応答を返し、その後要求メッセージ本体を処理してから最終的な応答を返すことが期待されています。 (詳しくは 100-continue を参照してください。)

サーバープッシュ

[65] HTTP/2 では、クライアント要求するかわりにサーバー要求クライアントへ送信し、 その後サーバーからクライアント応答を送信できます。

[66] 構文上はサーバーは任意の URL応答を送信できます。 実際には当該サーバーauthoritative であることなどいくつかの制限があります。

詳細はサーバープッシュおよび >>96 を参照。

接続を閉じる

[558] クライアントはいずれも任意の時点で接続を閉じて構いません >>553, >>73

[61] HTTP/2 では、まず GOAWAY フレームを送信するべきです >>60, >>90, >>73。 しかし送信しない実装もあります。 GOAWAY を参照。

[184] Firefox は、相手が GOAWAY なしで接続を閉じた場合でも、 (他に問題がなければ) 誤り符号 NO_ERRORGOAWAY を送信してから、接続を閉じます。 Chrome はすぐに接続を閉じます。

[576] は過負荷時に (503 を返すか、または) 直ちに接続を閉じても構いません >>577

[540] 接続はいつでも予告なく閉じられることがあります >>539 から、実装は、接続の終了に対して頑強でなければなりません。

[567] HTTP/0.9HTTP/1.0 では、 Keep-Alive が有効な場合を除き、 メッセージの終わりで接続も閉じなければなりません。

[537] 持続的接続の終了は、 Connection: close によって表します。

詳しくは close持続的接続の項を参照してください。

[4] HTTP/1.1 以下では、メッセージ本体の終了を接続を閉じることによって通知することがあります。

メッセージ本体の項を参照してください。

[561] は、下位層プロトコルの特性によりメッセージの一部又は全部が失われないように注意して接続を閉じる必要があります。 詳しくはTCPリセット問題を参照してください。

[571] CONNECT の項も参照してください。

[165] サーバーによっては FIN を受け取った時点で応答の残りの転送を取りやめるようなので、 クライアント応答の受信が終わるまで、要求の送信が終わったとしても接続を閉じてはいけません。

[64] HTTP/2 では、ストリーム識別子が枯渇するとそれ以上メッセージを送受信できなくなってしまいます。 クライアントは、新しい接続を確立して新しいストリームを作成できます >>62サーバーは、 GOAWAY フレームを送信してクライアントに新しい接続を開くように求められます >>62

[135] ChromeFirefox は、 abort a document による fetch の中止の際は、正常に (FIN で) 接続を閉じるようです。 IERST を使うようです。

エラーによる接続の終了

[5] メッセージ本体が存在し、 Transfer-Encoding: ヘッダーの最後の転送符号化chunked 以外である要求メッセージを受け取った時は、 400 応答を返して接続を閉じなければなりません >>3

[510] Content-Length: が無視されない場合で、 複数あったり非妥当だったりする場合は、 接続を閉じなければなりません >>3

[511] Content-Length: が無視されない場合で、 その長さのメッセージ本体を受け取らずに接続が閉じられたり、 タイムアウトしたりした時には、接続を閉じなければなりません >>3

[538] 下位ネットワークの障害や接続の当事者のシステム上の障害などによって、 メッセージの途中で接続が中断されたり、 何の送受信も発生しないまま長時間経過したりすることがあります。 こうした場合の処理については、メッセージメッセージ本体の項を参照してください。

[547] パイプライン化している場合で途中で接続が閉じられたときの処理は、 HTTPパイプラインの項を参照してください。

[40] サーバー死活監視を行うソフトウェアの中には、 TCP レベルでの検査を行うものもあります。これは TCP接続確立できることを確認すると、 すぐに切断するものです。この場合 HTTPメッセージを送受信することなく接続が終了しますから、 サーバーはそのような場合も適切に処理できる必要があります。

[559] は、クライアントが再試行すると期待して接続を閉じるよりは、 できれば持続的接続を維持して、一時的な過負荷はトランスポート層フロー制御に任せるべきです (閉じて再試行させる方が輻輳を悪化させるかもしれません) >>553

[560] クライアントメッセージ本体の送信中に接続を監視して、 が受信を望まず接続を閉じようとしていることがわかれば、 すぐに転送をやめて接続を閉じるべきです >>553

[580] 100413 も参照してください。

[578] 上流から非妥当応答を受け取った時、 転送するかわりに 502 応答を返すことができます。 Content-Length:非妥当な場合は更に接続を閉じなければならないこともあります。 詳しくは 502 を参照してください。

[74] HTTP/2 接続エラーの場合、 (GOAWAY の後) TCP接続を閉じなければなりません >>73

接続エラーを参照。

[77] 誤り符号 ENHANCE_YOUR_CALM (0xb) は、 過負荷を引き起こしかねない動作を peer が示したことを表します >>76

タイムアウト

[554] は普通はタイムアウトを設定しており、 活性状態でない接続をそれ以上維持しません。 >>553

[555] は、クライアントが同じにより多く接続して来るであろうことから、 タイムアウトを大きめにするかもしれません。 >>553

[556] クライアントタイムアウトを設定して、 必要のない接続をそれ以上維持しないかもしれません。

[557] タイムアウトしたいクライアントは、 当該接続graceful close するべきです >>553実装は定期的に接続を閉じる信号を監視して、 適宜応答するべきです >>553

[12] によっては、HTTP/1.0 応答を送り終えた後もしばらく接続を閉じないものがあるといわれています。

[71] nginx は、接続後何も送信しないでいると、タイムアウトにより何も返さずに接続を閉じるようです。

[264] nginx は標準状態では60s何も受信しないと、タイムアウトとするようです >>263

[154] 応答の受信後に次の要求を送信するため保持した状態の接続について、 Chrome は約300s、 Firefox は115s >>159 未使用なら、閉じるようです。 IE は60s未使用なら、 RST するようです >>141

[155] IE は、要求の送信があった後 3600s サーバーから送信がなければ、 RST するようです。 (どこから起算しているかは未調査。最後の受信?)

[156] FirefoxTCP keep alive (>>153) が無効に設定されている時は、 300s 間サーバーから送信がなければ、タイムアウトとして接続を閉じます >>142

[160] Chrome や、FirefoxTCP keep alive が有効な場合 (既定の状態) では、要求が送信された後応答を受信するまで (応答の一部を受信しようがしまいが) タイムアウトは無いように見えます。 (少なくても20時間以上は切断されません。)

[161] XHRtimeout 属性は、 接続の状態に関わらず、fetch の開始からの経過時間によりfetchを中断するものです。

[195] クライアントライブラリーによっては、 要求の開始や応答の受信開始からの経過時間でタイムアウトを決めるものもあります。 しかし応答完了まで (正常時でも) 非常に時間がかかるサーバーもありますから、 相当に大きな値とする必要があります。それでは逆に異常時にタイムアウトエラーとなるまでかなり時間がかかってしまいますから、 あまりよい実装戦略ではなさそうです。

[196] サーバーによっては、無限に長い応答を送ることがあります。 従って対話的でないクライアントは、正常な受信中であっても、 一定時間経過後に受信を打ち切るようにする必要がありそうです。

接続枠解放

[260] 持続的接続等で現時点で未使用の接続を後で利用する(可能性がある)ため保持している場合で、 実装全体での、あるいは特定サーバー宛ての接続数上限に達した場合、 その未使用接続を閉じて接続枠を開ける必要があるかもしれません。

要求の再試行

[541] 実装は、接続が閉じられた時に回復しないといけないかもしれないことを想定しておくべき (ought to) です >>539

[542] クライアントは、内向き接続が意図せず閉じられたとき、 中断された要求群がすべて冪等なメソッドだった場合には、 新しい接続を開いてその要求を自動的に再転送して構いません。 >>539

[544] 利用者エージェントは、何らかの手段で要求が本当は冪等であると分かっている場合や元の要求が適用されなかったと分かっている場合を除き、 冪等でないメソッド要求を自動的に再試行してはなりません>>539

[545] クライアントは、失敗した自動再試行を自動的に再試行するべきではありません >>539

[543] は、冪等でない要求を自動的に再試行してはなりません >>539

[565] Expect: 100-continue についても、 自動的な再試行に関する規定があります。

[75] HTTP/2TCP接続が閉じられたり RST されたりした時に openhalf-closed状態だったストリームは、 自動的に再試行することはできません >>73

[83] HTTP/2 では、次の場合、クライアント要求が処理されていないことが保証されます >>82

[86] これらの処理されていない要求は、失敗ではなく、 クライアント冪等か否かに関わらず自動的に再試行して構いません >>82

[107] 421 応答を受信したクライアントは、 冪等か否かに関わらず自動的に再試行して構いません >>90代替サービスから受信した場合は、当該代替サービス情報は削除しなければならず、 他の代替サービス起源サーバーに再試行して構いません。

421 参照。

[138] ChromeFirefoxIE も、 (GET でも POST でも) 持続的接続の2つ目の要求に対して応答を受信せず接続が切断された場合、 他の接続で改めて要求を送信するようです。

版の切り替え

[79] 誤り符号 HTTP_1_1_REQUIRED (0xd) は、 HTTP/2 ではなく HTTP/1.1 が必要であることを示します >>76

[179] その詳細な処理方法はどこでも規定されていません。いつこれを送れるのかも明確ではありません。

[183] HTTP/2 では再折衝が禁止されているため、クライアント認証が必要な時は HTTP_1_1_REQUIRED を送信するべきだとされています。

[174] ChromeFirefox も、 HEADERS より前に RST_STREAMGOAWAYHTTP_1_1_REQUIRED を受信すると、 HTTP/1.1 で接続し直すようです。

[175] 既に HTTP/1.1 の接続があれば、再利用するかもしれません (未検証)。

[176] ChromeHEADERS より後だと、 (RST_STREAM であっても) 接続を閉じて、ネットワークエラーとするようです。

[177] FirefoxHEADERS より後だと、 ネットワークエラーとするようです。

[178] ChromeFirefox も、再接続時には ALPNhttp/1.1 だけを指定します。

[180] (にも関わらず) サーバーALPNh2 を指定すると、 ChromeFirefoxHTTP/2 を使います。更に HTTP_1_1_REQUIRED を返すと、 Firefox は何度か試して諦めますが、 Chrome は無限に(?)試し続けます。

[201] 理論上は Upgrade: h2c によって HTTP/1 から HTTP/2 への切り替えを指示できます (が実装されていません)。

[200] Chrome は、 Alt-Svc: ヘッダーによって QUIC が利用可能なことを認識できます。

Alt-Svc: 参照。

ヘッダー

[521] Connection: ヘッダーは、接続の取り扱いを指定するものです。

[21] Expect: 100-continue はデータの送信のタイミングについて指示するものです。

100-continue 参照。

下位層プロトコル

[516] HTTPメッセージは下位の (トランスポート層セッション層の) プロトコルに依存しておらず、信頼できる輸送路であって、 要求の順序を保存した配送と応答の順序を保存した配送のみを要求しています >>515

[2] 実際には HTTP は、下位層プロトコルとして、

... のいずれかを用います。

[7] UPnP では UDP が使われます (SSDP)。
[37] HTTP over SCTP も提案されましたが、関心を集められませんでした。

[519] HTTP要求応答の構造と下位層プロトコルのデータ単位との対応関係は、 HTTP の仕様書の適用範囲外とされています >>515

[520] それ、アプリケーション層プロトコルの重要なところじゃないのでしょうか。。。

[59] HTTP/2 では HTTP/1.1 よりは詳しく規定があります (が完全ではありません)。

TCP

[192] HTTP over TCP は、従来標準的に用いられていました。 現在は安全ではないと考えられているため、徐々に HTTPS に置き換えられてきています。

[193] HTTP over TCPHTTPS と区別するため、 素のHTTPと呼ぶことがあります。

[41] HTTP over TCP は、 http: URL によって表されます。

[17] three-way handshake を経て TCP 接続が確立された後に TCP によって伝送されるオクテット列HTTP接続オクテット列です。 なお TCP セグメントの境界は HTTP接続に反映されません。 TCP セグメントの境界と HTTP接続上のメッセージ境界と一致しているとは限りません。


[33] TCP PSH フラグの取り扱いについて HTTP 特有の規定は特に無いと思われます。 (例えばHTTPメッセージの最後で PSH フラグを立てなければならないというようなことは特にありません。)

[16] TCP 緊急データHTTP の関係は明文化されていません。

[125] 応答の受信中に緊急データが含まれていた場合、次のように動作するようです (いずれも Windows)。


[18] HTTP接続を閉じる、あるいは閉じられるとは、 TCP 接続を閉じる、あるいは閉じられることを意味します。 HTTP接続を閉じると FIN セグメントが送信されることになります。 FIN セグメントを受信すると HTTP接続が相手に閉じられたことを表します。 その他に RSTタイムアウトなど TCP プロトコル上の規定や実装によって正常でない形で接続が閉じられることもあります。

[72] 応答の受信中に RST を受信した場合、次のように動作するようです (いずれも Windows)。

  • (前提として) Firefox はできるだけすぐにレンダリングを開始するようです。 IEChrome はある程度のデータを受信しないと処理開始しないようです。
  • FirefoxIE は、レンダリング開始後であっても、 RST を受信したら RST を受信した旨の非文書表示に切り替えます。 Chrome はレンダリング開始前ならそうしますが、開始後なら何も表示しません (開発者ツールにはエラーが表示されます)。
  • ただし Firefox は場合によっては切り替わらない、あるいは自動的に再試行しようとするようです (詳細不明)。

[124] TCPRST を受信した時点でまだアプリケーションに渡されていないデータの扱いは、 TCP の実装によって異なるようです。エラーとして扱う以外に相互運用可能な方法はなさそうです。

[152] ChromeFirefoxSO_NODELAYに設定 (Nagleアルゴリズムを無効化) するようです。

HTTPS でも TCP接続について Nagleアルゴリズムを無効化するようです。

[186] HTTPクライアントライブラリー等で Nagleアルゴリズムを無効化しないものも少なくありません。 そのためにTCP/IPスタック内で送信待ちが発生して、応答の受信までに無駄な遅延が生じることがあります。 (気が付きにくいです。) プロトコルの仕様と用法から、 HTTPNagleアルゴリズムは不要です。 (WebSocket なら利用方法によっては有効に働くかもしれませんが、一概にはいえないのでアプリケーションWebブラウザー側で適当に扱うべきでしょう。)

[275] Nagleアルゴリズムを無効にしないのは、Web互換では無いようです >>270


[153] ChromeFirefoxSO_KEEPALIVE (TCP keep alive) を使うようです。 Chrome は最初の keep alive 送信まで (TCP_KEEPIDLE) 45s、 二度目以降の送信まで (TCP_KEEPINTVL) 45s とします (TCP_KEEPCNT は未設定で OS の既定値) >>145Firefox はより細かく調整します >>143

TCP_KEEPIDLETCP_KEEPINTVL (と TCP_KEEPCNT) は Linux のみのオプションなので、他の OS では設定され(でき)ません。

[173] FirefoxHTTP/2 の時 TCP keepalive を無効にし、かわりに 90s ほどの間を置いて HTTP/2 PING を送ります。返答がなければ INTERNAL_ERRORGOAWAY を送信して接続を閉じます。一方 ChromePING を送っておらず、 HTTP/1 同様に TCP keepalive を使っているようです。


[34] なお、通常は HTTP over TCPHTTP over TLS over TCP は別のポートを使いますが、両方を同じポートで受け付けられないこともありません (両者は区別可能です)。

[163] Apachenginx は、 HTTPS のポートに平文の HTTP要求のようなものが書き込まれると、 400 応答を返して切断するようです。

[164] 他のHTTPサーバーの実装は、何も返さず直ちに閉じたり、 純粋に TLS として扱ってエラーを返して閉じたり、 RST を送ったりするようです。

ポート

[189] 80HTTP / http: URL scheme既定のポート番号です。ほとんどの HTTP over TCP サーバーは、 80 番を使っています。

[273] 90年代には既定のポート以外の Webサーバーもたまに見かけましたが、 次第に既定のポート以外あまり使わなくなりました。

[274] 現在でも、 逆プロキシからのみアクセスを受け付けるアプリケーションサーバー開発者の手元で実行される開発中のアプリケーションサーバー、 主目的がWebサーバーではないプログラムの制御機能を Web 経由で利用できる形のサーバーなど、 一般的な利用者に直接見えない形では既定のポート以外が使われる場面があります。

[191] 素のHTTPでは、 80008080 がしばしば使われます。

[190] port blocking も参照。

TLS

[14] SSLTLS でも HTTP は利用されます。

[42] HTTP over TLS over TCP は、 https: URL によって表されます。

[271] HTTP over TLS over TCP では、 443既定のポート番号です。

[272] 詳細は HTTPS を参照。

[282] Opportunistic Security for HTTP/2 に対応している場合、 本来 HTTP over TCP を使う http: URL へのアクセスも、 HTTP over TLS を使います。

Unix ドメインソケット

[15] (同じ Unix 環境上で動作する) 逆串からアプリケーション鯖への通信などに Unixドメインソケットを使う場合があります。

[30] が予めソケットを作成しておき、クライアントがこれに接続することで、 当該ソケットを使った読み書きが HTTP接続となります。ソケットによる接続を閉じる、 または閉じられると、 HTTP接続が閉じる、あるいは閉じられることとなります。

[8] HTTP に特化した仕様書は特にありません。

[276] Unixドメインソケットを使った HTTP のアクセスを表す URL はありません。主用途がアプリケーションサーバーへの接続なので、 それが必要となることも無さそうです。

[277] 要求Host: ヘッダーが無い場合、 要求に含まれる情報だけから実効要求URLを確定できません。 Host: ヘッダーが無い場合をエラーとして扱うか、 サーバーの設定によって自身の既定のホストポートを決めておく必要があります。

[29] 次のような実装例があります。

HTTP CONNECT

[129] HTTP CONNECT メソッドは任意の TCP アプリケーショントンネリングに使うことができますので、 HTTP の下位層としても使うことができます。

[130] しかし通常は HTTPSトンネリングに使うので、直接 CONNECT トンネル内が HTTP となることはありません。

HTTPSCONNECT を参照。

SOCKS

[22] SOCKS proxy (SOCKS プロトコルによる TCP/IP トンネル) を介して HTTP クライアントから HTTP 接続することがあります。

[25] 多くのWebブラウザーその他の HTTP クライアントが、の一種として SOCKS に対応しています。また socksifytsocks のようなソフトウェアによって通常の TCP/IP 接続SOCKS接続に置き換えられることもあります。

[23] 他の TCP アプリケーションと同様に、SOCKS 接続するべき IPアドレスまたはホスト名TCP ポートを指定して接続を確立します。 以後 SOCKS プロトコル上の送受信データが HTTP接続となります。 SOCKS接続が閉じる、あるいは閉じられると、 HTTP接続が閉じる、 あるいは閉じられることとなります。

[32] SOCKS の下位層の TCP/IP ネットワークエラーその他の原因で SOCKS 接続が異常に閉じられることがあります。

[24] HTTP に特化した仕様書は特にありません。

MIME 型

[563] 接続そのものではありませんが、接続上の要求の列または応答の列を表す MIME型 application/http があります。

URL

[31] HTTP接続自体を表す URL scheme はありません。 HTTP接続を使った資源へのアクセスを表す URL は、 http:, https: を参照。

[202] HTTPプロキシhttp: URL で表すことがあり、これはある意味でHTTP接続を表す URL とも言えるかもしれません。

歴史

[1] HTTP (RFC 1945 1.2, RFC 2068 1.3, RFC 2616 1.3)
connection
A transport layer virtual circuit established between two {1945} application programs for the purpose of communication.
接続
2つの応用プログラム間の通信目的で確立される転送層仮想回路。

[575] Re: Fetch: HTTP authentication and CORS ( (Jonas Sicking 著, 版)) http://lists.w3.org/Archives/Public/public-webapps/2013AprJun/0502.html

[581] RFC 6202 - Known Issues and Best Practices for the Use of Long Polling and Streaming in Bidirectional HTTP ( ( 版)) http://tools.ietf.org/html/rfc6202#section-5.1

[582] draft-mogul-http-ooo-00 - Support for out-of-order responses in HTTP ( ( 版)) https://tools.ietf.org/html/draft-mogul-http-ooo-00

[13] draft-zhu-http-fullduplex-08 - Implications of Full-Duplex HTTP ( 版) https://tools.ietf.org/html/draft-zhu-http-fullduplex-08

[39] Part2 - browsersec - Browser Security Handbook, part 2 - Browser Security Handbook - Google Project Hosting ( 版) https://code.google.com/p/browsersec/wiki/Part2#Simultaneous_connection_limits

[139] How to change the default keep-alive time-out value in Internet Explorer ( 版) https://support.microsoft.com/en-us/kb/813827

After the connection is idle for one minute, Internet Explorer resets the connection.

[140] 205140 – Prefs: remove "network.http.*.timeout" ( 版) https://bugzilla.mozilla.org/show_bug.cgi?id=205140

[141] Internet Explorer error "connection timed out" when server does not respond ( 版) https://support.microsoft.com/en-us/kb/181050

Internet Explorer imposes a time-out limit for the server to return data. By default, the time-out limit is as follows:

Internet Explorer 4.0 and Internet Explorer 4.01 5 minutes

Internet Explorer 5.x and Internet Explorer 6.x 60 minutes

Internet Explorer 7 and Internet Explorer 8 60 minutes

[142] 1024015 – network.http.response.timeout breaks applications with long lived http connetions ( 版) https://bugzilla.mozilla.org/show_bug.cgi?id=1024015

[143] 444328 – TCP-level keep alive timer ( 版) https://bugzilla.mozilla.org/show_bug.cgi?id=444328

[144] HTTP keep-alive connection timeouts | FastMail Weblog ( 版) http://blog.fastmail.com/2011/06/28/http-keep-alive-connection-timeouts/

Opera 11.11 – 120 seconds

Chrome 13 – at least 300 seconds (server closed after 300 second timeout)

IE 9 – 60 seconds (changeable in the registry, appears to apply to IE 8/9 as well though the page only mentions IE 5/6/7)

Firefox 4 – 115 seconds (changeable in about:config with network.http.keep-alive.timeout preference)

Interestingly one of the other things I noticed while doing this test with Wireshark is that after 45 seconds, Chrome would send a TCP keep-alive packet, and would keep doing that every 45 seconds until the 5 minute timeout. No other browser would do this.

[145] Issue 27400 - chromium - Long lived connections are being dropped by some network setups - An open-source project to help move the web forward. - Google Project Hosting ( 版) https://code.google.com/p/chromium/issues/detail?id=27400

[146] 947391 – HTTP connections (exc. XHR, SPDY) should have a response timeout ( 版) https://bugzilla.mozilla.org/show_bug.cgi?id=947391

[147] 1005808 – New response timeout is affecting request requiring significant processing time ( 版) https://bugzilla.mozilla.org/show_bug.cgi?id=1005808

[148] Bug 102079 – Disable Nagle algorithm on WebSocket implementation ( 版) https://bugs.webkit.org/show_bug.cgi?id=102079

[149] WebSocket Nagle アルゴリズム問題 ( 版) https://gist.github.com/uupaa/6281381

[150] Issue 450258 - chromium - Websocket is stalling "OnMessage" javascript events until a certain number of bytes or a timer elapses - An open-source project to help move the web forward. - Google Project Hosting ( 版) https://code.google.com/p/chromium/issues/detail?id=450258

Windows 7 delays acks very aggressively for up to 200ms. If the server is using the Nagle algorithm, it won't send new messages until the acks arrive (or the send buffer fills).

Any decent WebSocket server should have Nagle disabled, which is why we haven't seen this until now.

Fortunately (?) pywebsocket in standalone mode does not disable the Nagle algorithm, and so I was able to reproduce quite easily. I then used Wireshark to confirm that the issue was happening at the TCP/IP level.

The best fix is to disable Nagle on the server. This will avoid other, more subtle, problems that the Nagle algorithm can cause.

[151] 542401 – set TCP_NODELAY for all SocketTransport sockets (not just SSL) ( 版) https://bugzilla.mozilla.org/show_bug.cgi?id=542401

[157] IE9、IE10のリクエストタイムアウト時間 ( 版) https://social.technet.microsoft.com/Forums/ja-JP/5d64ea16-39cc-4f30-8077-ebf65a52f298/ie9ie10?forum=internetexplorerja

手元の次環境で、SleepするだけのCGIにリクエストした所、ともに受信タイムアウトは60分ちょうどでした。

Win8 & IE10

Win7 & IE9

HTTPレスポンス受信に無通信のまま60分経つと、IE側から切断していました。(最初の受信データかによらず)

レジストリにタイムアウト値(ReceiveTimeout)は設定していません。

# 「切断する」とは、FINパケットを先にどちらが送出したかで確認を行いました。

 

上記リンク先のIE9が5分後にリクエストをリトライする事象は、

最初、私もこれに引っかかってしまいましたが、

サーバにApache2.2をデフォルト設定のままで使用していると発生すると思います。

CGIがいつまでも応答がない場合に、Apacheがコネクションを切断してしまうためでした。(Timeoutの第3項も参照)

このときIE側からは、すぐに別コネクションで接続が行われ、同一のリクエストを送信していました。

(よーするに、1TCPコネクション内の再送ではなく、アプリレベルの再送)

設定変更すると5分以上経ってもIEは受信し続けてくれました。

[158] HTTPS and Keep-Alive Connections - IEInternals - Site Home - MSDN Blogs ( 版) http://blogs.msdn.com/b/ieinternals/archive/2011/03/26/https-and-connection-close-is-your-apache-modssl-server-configuration-set-to-slow.aspx

In the first, a thoughtful web developer or operations team reasons: “Hey, HTTPS connections are expensive to maintain on the server. Let’s be sure to tear those down as soon as possible to free up the server to accept new connections.”  That, of course, completely misses the point that if the server wasn’t tearing down the connections, the server would be under significantly lighter load to begin with! Sites that were deliberately written with this bad pattern load slowly in all browsers.

We also found another root cause—ancient advice for the configuration of Apache+OpenSSL. Prior to IE6, ancient and unpatched versions of IE sometimes encountered connection failures when interacting with HTTPS servers when Keep-Alive is used. That problem was fixed nearly a decade ago, but outdated 1999-era configuration advice continues to harm performance for unaware server administrators:

[159] Network.http.keep-alive.timeout - MozillaZine Knowledge Base ( 版) http://kb.mozillazine.org/Network.http.keep-alive.timeout

[166] javascript - Max parallel http connections in a browser? - Stack Overflow ( 版) http://stackoverflow.com/questions/985431/max-parallel-http-connections-in-a-browser/985704

[172] gecko-dev/nsHttpConnection.cpp at master · mozilla/gecko-dev ( 版) https://github.com/mozilla/gecko-dev/blob/master/netwerk/protocol/http/nsHttpConnection.cpp

// Disable TCP Keepalives - use SPDY ping instead.

rv = DisableTCPKeepalives();

[181] 1091263 – [http/2] HTTP_1_1_REQUIRED error code ( 版) https://bugzilla.mozilla.org/show_bug.cgi?id=1091263

[182] Issue 431306 - chromium - Implement HTTP/2 error code HTTP_1_1_REQUIRED. - An open-source project to help move the web forward. - Google Project Hosting ( 版) https://code.google.com/p/chromium/issues/detail?id=431306

[187] ( 版) http://cpansearch.perl.org/src/MLEHMANN/AnyEvent-HTTP-2.22/Changes

- do not recurse on POST requests, as per HTTP/1.[01] (this might

change as the recommendation isn't followed by anybody else).

[188] Support full-duplex HTTP streaming · Issue #229 · whatwg/fetch ( 版) https://github.com/whatwg/fetch/issues/229

[194] Allow for a request to finish after a response starts to arrive · whatwg/fetch@3a41b6f ( 版) https://github.com/whatwg/fetch/commit/3a41b6f04996d4aac13ecad5b38635827dcd0df3

[220] 1190136 – Firefox should decide whether reuse connection separately for IPv4 and IPv6 ( ()) https://bugzilla.mozilla.org/show_bug.cgi?id=1190136

[221] cURL - How To Use ( ()) https://curl.haxx.se/docs/manpage.html#--http2-prior-knowledge

--http2-prior-knowledge

(HTTP) Tells curl to issue its non-TLS HTTP requests using HTTP/2 without HTTP/1.1 Upgrade. It requires prior knowledge that the server supports HTTP/2 straight away. HTTPS requests will still do HTTP/2 the standard way with negotiated protocol version in the TLS handshake.

[222] cURL - How To Use ( ()) https://curl.haxx.se/docs/manpage.html#--keepalive-time

--keepalive-time <seconds>

This option sets the time a connection needs to remain idle before sending keepalive probes and the time between individual keepalive probes. It is currently effective on operating systems offering the TCP_KEEPIDLE and TCP_KEEPINTVL socket options (meaning Linux, recent AIX, HP-UX and more). This option has no effect if --no-keepalive is used. (Added in 7.18.0)

[223] cURL - How To Use ( ()) https://curl.haxx.se/docs/manpage.html#--unix-socket

--unix-socket <path>

(HTTP) Connect through this Unix domain socket, instead of using the network. (Added in 7.40.0)

[242] Issue 170165 - chromium - Websocket handshake delay when server is unavailable - Monorail ( ()) https://bugs.chromium.org/p/chromium/issues/detail?id=170165

[249] Ajax Performance ( ()) http://www.tophotelshongkong.com/en/ajaxperformance.html

IE8: The Performance Implications

March 7, 2008 on 1:25 am | In ajax | No Comments

Mix08 is here, and with it the first beta of IE8. John has a great roundup of the JS/Dom work, noting that “Internet Explorer 8 is our release.” He’s right.

I’ll run through a few of the items that have particular implications for performance.

This one is the most exciting for me: the IE team has finally upped the connection limit to 6 per host from the default of 2. I’ve talked before about DNS tricks to get around the 2 connection limitation, but having this support out of the box will be a great assistance in the war on round-trip latency as it’s easier to make more expensive network calls in parallel. This is especially sweet for Comet and the like where the persistent connection could previously monopolize half of the connections to your site. As you would expect, Joe Walker of DWR is happy.

One thing I haven’t seen mentioned anywhere is the total connection limit. Previous versions supported 2 per host and 6 total. Is the new version 6 per host / 6 total or 6 per host / 18 total. I really doubt it on the latter, but if no one has the answer I’ll grab the beta this weekend and test it out.

[261] Retrying HTTP Requests ( ()) https://mnot.github.io/I-D/httpbis-retry/

[262] POST request fails on certain sites, showing connection reset page (Regressed) | Firefox Site Compatibility ( ()) https://www.fxsitecompat.com/en-CA/docs/2016/post-request-fails-on-certain-sites-showing-connection-reset-page/

Firefox 46 has changed the way to handle broken connections so that it will no longer automatically retry unsafe requests such as POST. However, various Web sites do not work with the new behaviour, resulting in an error page “connection to the server was reset”, because they expect the browser to retry connections even for POST requests. KanColle, a popular Japanese Flash game is known to be affected.

[267] nginx ちょっと不思議だったリクエストリトライのお話 - Cybozu Inside Out | サイボウズエンジニアのブログ () http://blog.cybozu.io/entry/2016/05/09/080000

[268] Apache Tomcat Configuration Reference (6.0.45) - The HTTP Connector (Craig R. McClanahan著, ) http://tomcat.apache.org/tomcat-6.0-doc/config/http.html

tcpNoDelay

If set to true, the TCP_NO_DELAY option will be set on the server socket, which improves performance under most circumstances. This is set to true by default.

[269] Apache Tomcat Configuration Reference (6.0.45) - The HTTP Connector (Craig R. McClanahan著, ) http://tomcat.apache.org/tomcat-6.0-doc/config/http.html

socket.tcpNoDelay

(bool)same as the standard setting tcpNoDelay. Default value is false

socket.soKeepAlive

(bool)Boolean value for the socket's keep alive setting (SO_KEEPALIVE). Default is false.

socket.ooBInline

(bool)Boolean value for the socket OOBINLINE setting. Default value is true

socket.soReuseAddress

(bool)Boolean value for the sockets reuse address option (SO_REUSEADDR). Default value is true

socket.soLingerOn

(bool)Boolean value for the sockets so linger option (SO_LINGER). Default value is true. This option is paired with the soLingerTime value.

socket.soLingerTime

(bool)Value in seconds for the sockets so linger option (SO_LINGER). Default value is 25 seconds. This option is paired with the soLinger value.

socket.soTimeout

(int)Value in milliseconds for the sockets read timeout (SO_TIMEOUT). Default value is 5000 milliseconds.

socket.soTrafficClass

(byte)Value between 0 and 255 for the traffic class on the socket, 0x04 | 0x08 | 0x010

[278] Webmention () https://webmention.net/draft/#h-limits-on-get-requests

Receivers should place limits on the amount of data and time they spend fetching unverified source URLs. For example, if a source URL doesn't respond within 5 seconds, it can treat that as a failure. Similarly, the receiver can fetch only the first 1mb of the page, since any reasonable HTML or JSON page will be smaller than that.

[279] HTTP/1.1 and Nagle's Algorithm () https://www.w3.org/Protocols/HTTP/Performance/Nagle/

[280] draft-pardue-quic-http-mcast-00 - Hypertext Transfer Protocol (HTTP) over multicast QUIC () https://tools.ietf.org/html/draft-pardue-quic-http-mcast-00

[281] nsHttpConnectionMgr.cpp - DXR () https://dxr.mozilla.org/mozilla-beta/source/netwerk/protocol/http/nsHttpConnectionMgr.cpp#2727

// For backup connections, we disable IPv6. That's because some users have

// broken IPv6 connectivity (leading to very long timeouts), and disabling

// IPv6 on the backup connection gives them a much better user experience

// with dual-stack hosts, though they still pay the 250ms delay for each new

// connection. This strategy is also known as "happy eyeballs".

[286] Service Name and Transport Protocol Port Number Registry () https://www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.xhtml?&page=2

[287] Clarify rules around half-closed TCP connections · Issue #22 · httpwg/http11bis () https://github.com/httpwg/http11bis/issues/22

[288] Abortable fetch (jakearchibald著, ) https://github.com/whatwg/fetch/commit/0bcd5dfc71ef44319873887f4b83119bd6d0b71d

[293] Warp should respond with HTTP_1_1_REQUIRED for connection takeovers. · Issue #417 · yesodweb/wai () https://github.com/yesodweb/wai/issues/417

[294] 516237 - Chrom{e,ium} refuses to talk HTTP/2 to a server once it's seen HTTP_1_1_REQUIRED for any resource. - chromium - Monorail () https://bugs.chromium.org/p/chromium/issues/detail?id=516237

[295] 685741 - ERR_UNEXPECTED Displays briefly before page loads - chromium - Monorail () https://bugs.chromium.org/p/chromium/issues/detail?id=685741

[296] 1091263 - [http/2] HTTP_1_1_REQUIRED error code () https://bugzilla.mozilla.org/show_bug.cgi?id=1091263

[297] [WFLY-7662] CLIENT-CERT authentication doesn't work - JBoss Issue Tracker () https://issues.jboss.org/browse/WFLY-7662?_sscc=t

[298] errors: change timeout errors from 408 to 500 HTTP status code (andreastt著, ) https://github.com/w3c/webdriver/commit/c377c21186f672105a05383d5152e0a3b2a00374

[299] HTTP status code 408 causes clients to retry · Issue #1287 · w3c/webdriver () https://github.com/w3c/webdriver/issues/1287

[300] errors: change timeout errors from 408 to 500 HTTP status code by andreastt · Pull Request #1292 · w3c/webdriver () https://github.com/w3c/webdriver/pull/1292