#このページで確認できること
- HTTP/1.1 の開始行とヘッダーフィールドがテキスト形式であることを
curl -vとncで確認する - Keep-Alive によるコネクション再利用を curl の出力で確認する
- Head-of-line blocking がどこで発生するかをシーケンスで確認する
- 試すURL: Status Code Lab の
/status/200ほか(要ローカルnginx)
実装上の制約: 本ラボの検証URLは平文HTTP(ローカルのnginx)前提です。TLS越しにワイヤを観測する場合は SSLKEYLOGFILE などの復号設定が必要です。
#特徴
- テキスト形式の開始行とヘッダー: リクエストライン・ステータスライン・ヘッダーフィールドはテキストとして読めるため、
telnetやncで手打ちできる。ボディは画像を含む任意のオクテット列であり、テキストとは限らない。 - 持続的接続 (Keep-Alive): HTTP/1.1 ではデフォルトでコネクションを再利用する。
Connection: closeで明示的に切断。 - パイプライン化は主要ブラウザでは通常使われない: 仕様上は複数リクエストを応答待ちせずに送れるが、サーバーは応答をリクエスト順に返す必要がある。応答順序の制約や中間装置との互換性から、主要ブラウザ実装では一般に利用されていない。
- Head-of-line blocking: パイプライン化した場合でも、先行レスポンスが完了するまで後続レスポンスを返せない。ブラウザは複数コネクションで緩和することがあるが、本数は実装や環境に依存する。
- メッセージボディの長さ:
Content-LengthやTransfer-Encoding: chunkedのほか、メソッド・ステータスによるボディなしの規則や、接続クローズによって決まる場合がある。
#通信シーケンス
participants: Client, Server Client -> Server: TCP SYN Server --> Client: SYN/ACK Client -> Server: ACK note: TCP 3-way handshake 完了 Client <-> Server: TLS handshake (ClientHello / ServerHello ...) Client -> Server: GET /index.html HTTP/1.1 Server --> Client: HTTP/1.1 200 OK + headers Server --> Client: Response body note: Keep-Alive により同一コネクションで次のリクエストを送れる Client -> Server: GET /style.css HTTP/1.1
participants: Client, Server Client -> Server: GET /slow (処理に時間がかかる) Client -> Server: GET /fast (応答を待たずに送信) note: /fast の処理が先に終わっても、応答はリクエスト順に返す Server --> Client: 200 OK (/slow, ようやく完了) Server --> Client: 200 OK (/fast)
#検証コマンド
curl — HTTP/1.1 を明示して観測$ curl -v --http1.1 http://localhost:8080/status/200 # -v で「> GET / HTTP/1.1」「< HTTP/1.1 200 OK」の生メッセージが見える $ curl -v --http1.1 -H 'Connection: close' http://localhost:8080/status/200 # レスポンス後にコネクションが閉じられることを確認nc — 手打ちでリクエストを送る
$ printf 'GET /status/200 HTTP/1.1\r\nHost: localhost\r\nConnection: close\r\n\r\n' \ | nc localhost 8080 # 開始行とヘッダーフィールドがテキスト形式であることを体感できる応答例 (主要ヘッダーの抜粋)
HTTP/1.1 200 OK
Server: nginx
Content-Type: text/plain
Connection: close
X-Demo: status-200
200 OK
#観測ポイント
| curl | -v でリクエスト/レスポンスの生テキスト。--http1.1 で強制。2回連続リクエストで * Re-using existing connection が出れば Keep-Alive が効いている。 |
|---|---|
| DevTools | Network → 対象リクエスト → Headers で Protocol 列 (http/1.1)。Timing タブで Stalled(コネクション待ち)を観測。 |
| Proxy | HTTP/1.1を終端するプロキシは、メッセージを解析して転送する。Via: 1.1 proxy-name の付与、Hop-by-hop ヘッダー(Connection, Keep-Alive)が次のホップへそのまま転送されないことを確認。 |
| tcpdump / Wireshark | 平文なら tcp port 8080 + Follow TCP Stream でメッセージ全体が読める。3-way handshake → リクエスト → レスポンスの順序を確認。 |
| TLS inspection | 装置がTLSを終端し、クライアント側でHTTP/1.1をネゴシエートした場合は、復号後のHTTP/1.1メッセージを解析する。ヘッダーの追加・正規化の有無をdirect接続と比較。 |
$ sudo tcpdump -i lo0 -A 'tcp port 8080' # -A でASCII表示。テキストのままリクエストラインが読める
#HTTP/2 へ続く課題
HTTP/1.1 の限界がそのまま HTTP/2 の設計動機になっています。
- 応答順序の制約と、非パイプライン時の直列処理 → HTTP/2 の多重化(ストリーム)
- 毎回同じヘッダーをテキストで送る冗長性 → HPACK ヘッダー圧縮
- テキスト解析のコストと曖昧さ → バイナリフレーミング
続き: HTTP/2 →