HTTPの「1xxステータスコード」を理解する:なぜサーバーは「ちょっと待て」と言うのか
ネットワークエンジニアとして現場に立っていると、200 OKや404 Not Foundといった「結果」ばかりに目が行きがちです。しかし、HTTPの奥深さは、リクエストとレスポンスの「間」にこそ隠されています。
今回深掘りするのは、あまり表舞台には出てこない「1xx Informational(情報レスポンス)」です。なぜサーバーは、いきなり本題(200 OK)を返さずに、わざわざ中間メッセージを送るのか。今日は、その実務的な意味と挙動を紐解いていきましょう。
—
1. 100 Continue:効率化のための「お伺い」
大規模なファイルアップロードや、認証トークンが必須のPOSTリクエストを想像してください。もし、クライアントが数GBのデータを送信し終えた直後に、サーバーが「認証失敗(401)」や「データ形式エラー(400)」を返したらどうなるでしょう?
クライアントは膨大な通信帯域と時間を無駄にし、サーバーも不要なデータ処理にリソースを割くことになります。この悲劇を防ぐための紳士協定が `100 Continue` です。
通信フローの裏側
1. クライアント: `Expect: 100-continue` というヘッダーを付けてリクエストを投げる。
2. サーバー: 受け取り可能か判断し、OKなら `100 Continue` を返す。
3. クライアント: サーバーからの100を受け取った後に、ボディ(実データ)を送信する。
もしサーバーがエラーを返せば、クライアントはデータを送信することなく、その場で処理を中断できます。これは、帯域が限られたモバイル環境や、巨大なペイロードを扱うAPIにおいて非常に賢い戦略です。
実践:curlで挙動を確認する
実際に `100 Continue` が発生するフローを観察するには、`curl` の `-v` オプションとヘッダー指定が役立ちます。
Expectヘッダーを明示的に付与してリクエスト
curl -v -H “Expect: 100-continue” -X POST http://example.com/upload –data-binary @large_file.bin
出力には以下のようなやり取りが記録されます
> POST /upload HTTP/1.1
> Expect: 100-continue
< HTTP/1.1 100 Continue
(ここで一旦止まり、その後にデータが送信される)
---
2. 101 Switching Protocols:Websocketへの招待状
`101 Switching Protocols` は、よりドラマチックです。これは、HTTPという「一度きりのやり取り」を卒業し、永続的な双方向通信へと移行するための合図です。
最も典型的な例は WebSocketへのアップグレード です。
プロトコル切り替えのメカニズム
1. クライアント: `Upgrade: websocket` ヘッダーを付けて接続を要求。
2. サーバー: 承諾する場合、`101 Switching Protocols` を返し、通信路を維持したままプロトコルを切り替える。
この瞬間から、通信はHTTPの作法から解放され、軽量なバイナリフレームによる通信が始まります。インフラ側でこれを扱う際は、ロードバランサー(NginxやHAProxy)の設定に細心の注意が必要です。
Nginxでの設定例
プロキシサーバーが `101` を理解できないと、接続は即座に切断されます。
location /ws/ {
proxy_pass http://backend_cluster;
# WebSocket通信にはプロトコルのアップグレード設定が必須
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection “upgrade”; # 101を引き出すための鍵
# タイムアウト設定も忘れずに(切断を防ぐ)
proxy_read_timeout 86400s;
}
—
3. 実務で遭遇するトラブルとデバッグの極意
1xx系のステータスコードを扱う際、エンジニアが最もハマりやすいのが 「レガシーな中継機器」 です。
HTTP/1.1から導入されたこれらのコードは、非常に古いプロキシや一部の特殊なファイアウォール(WAF)が「未知のレスポンス」として破棄したり、不適切なヘッダー変換を行ったりすることがあります。
トラブルシューティングのTips
- クライアント側の待機処理: Fetch APIなどを使う際、デフォルトでは `100 Continue` を意識する必要はありませんが、低レイヤーのライブラリ(Pythonの `http.client` など)を触る際は、レスポンスの取得が「2回」発生する可能性があることを考慮してください。
- ログ解析: サーバーのアクセスログに `100` が記録されないケースが多々あります。これは仕様上正しいのですが、デバッグ時には `tcpdump` や `Wireshark` でパケットレベルまで潜り、「サーバーが本当に100を返しているか」を物理的に確認するのが最短ルートです。
Pythonでリクエストの挙動を追う際のヒント
import http.client
conn = http.client.HTTPConnection(“example.com”)
conn.putrequest(“POST”, “/upload”)
conn.putheader(“Expect”, “100-continue”)
conn.endheaders()
サーバーからの100レスポンスを明示的に取得する
response = conn.getresponse()
if response.status == 100:
print(“サーバーが準備OKと言ったので、データを流し込みます”)
conn.send(b”large_payload_data”)
—
最後に:プロトコルの「行間」を読めるエンジニアへ
HTTPのステータスコードは、単なる数値ではありません。それはサーバーとクライアントの間で交わされる「対話の作法」です。
1xxレスポンスを正しく理解し、適切に制御できるようになると、APIのレスポンス速度向上や、WebSocketを用いたリアルタイム通信の安定性向上など、インフラとしての「質」が一段階上がります。
教科書を閉じて、次はぜひブラウザの開発者ツールやパケットキャプチャを開いてみてください。そこに、あなたの知らない「ネットワークの呼吸」が見えてくるはずです。
コメント