HTTPステータスコードとヘッダの基礎 — 2xx/3xx/4xx/5xxとキャッシュ制御
TL;DR
HTTPはWebの通信プロトコルです。ブラウザからのリクエストに対して、サーバーはステータスコードとヘッダをセットで返します。ステータスコードは「成功/転送/クライアントエラー/サーバーエラー」を3桁の数字で表し、ヘッダはキャッシュ期間・コンテンツタイプ・リダイレクト先など補足情報を運びます。CDNやCloudflareを正しく設定するにはこの仕組みを理解することが前提になります。
HTTPの基本 — リクエストとレスポンス
ブラウザがURLにアクセスするとき、裏では次のやり取りが行われています。
- リクエスト: ブラウザがサーバーに「このリソースをください」と送る
- レスポンス: サーバーがステータスコード・ヘッダ・ボディ(コンテンツ)を返す
テキストとして表すと以下のような構造です。
リクエスト(抜粋)
GET /articles/cdn-basics-why-cloudflare/ HTTP/1.1
Host: infradb.dev
Accept: text/html
レスポンス(抜粋)
HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
Cache-Control: public, max-age=3600
ETag: "abc123"
ステータスコードはレスポンスの1行目に入ります。ヘッダはステータスコードに続き、空行の後にボディ(HTML本文など)が続きます。
ステータスコードの分類
ステータスコードは先頭の1桁でカテゴリが決まります。
| 先頭桁 | 分類 | 意味の概要 |
|---|---|---|
| 1xx | 情報 | 処理継続中(通常はアプリ側で意識しない) |
| 2xx | 成功 | リクエストが正常に処理された |
| 3xx | リダイレクト | 別のURLへ転送する |
| 4xx | クライアントエラー | リクエスト側の問題 |
| 5xx | サーバーエラー | サーバー側の問題 |
2xx — 成功
| コード | 名称 | 使われる場面 |
|---|---|---|
| 200 | OK | 通常のページ取得・API成功。最も基本的な成功レスポンス |
| 201 | Created | POSTでリソースを新規作成したとき(REST APIでよく使う) |
| 204 | No Content | 処理は成功したがボディが不要なとき(DELETE後など) |
200 OK はHTTPで最も頻繁に返るコードです。ブラウザはこれを受け取るとコンテンツを描画します。
3xx — リダイレクト
| コード | 名称 | 特徴 |
|---|---|---|
| 301 | Moved Permanently | 恒久転送。ブラウザとGoogleがURLを更新する |
| 302 | Found | 一時転送。ブラウザは転送するが、元URLを記憶し続ける |
| 304 | Not Modified | キャッシュが有効なのでボディは返さない(後述) |
301と302の使い分けは実務で頻繁に問われます。詳細は後述の「301 vs 302 — リダイレクトの使い分け」を参照してください。
4xx — クライアントエラー
| コード | 名称 | 意味と原因 |
|---|---|---|
| 400 | Bad Request | リクエストの形式が不正(パラメータ欠損など) |
| 401 | Unauthorized | 認証が必要。未ログイン状態でアクセスした場合など |
| 403 | Forbidden | 認証済みだがアクセス権がない。サーバーはリソースを認識している |
| 404 | Not Found | リソースが存在しない。URLが間違っているか削除された場合 |
| 429 | Too Many Requests | レートリミット超過。APIの呼び出し上限を超えた場合など |
401と403の違いは混同されやすい点です。401は「誰だかわからない(認証が要る)」、403は「誰だかわかっているが許可しない」というニュアンスの違いがあります。
429はAPIを使うシステムでよく遭遇します。Cloudflareがボット対策でリクエストを絞る際にも返されることがあります。
5xx — サーバーエラー
| コード | 名称 | 意味と原因 |
|---|---|---|
| 500 | Internal Server Error | サーバー内部の汎用エラー。コードのバグや設定ミスが多い |
| 502 | Bad Gateway | 上流サーバーから不正なレスポンスが返った(後述) |
| 503 | Service Unavailable | サーバーが過負荷または停止中。メンテナンス時にも使う |
| 504 | Gateway Timeout | 上流サーバーがタイムアウトした(後述) |
502/503/504 — ゲートウェイ・プロキシ系エラーの意味
CDNやリバースプロキシを挟む構成では、5xx系エラーの中でも 502/503/504 が特に重要です。
ブラウザ → Cloudflare(CDN)→ オリジンサーバー
この構成において、エラーがどの層で起きているかを判別することがインシデント対応の第一歩になります。
| コード | 発生箇所のイメージ | 典型的な原因 |
|---|---|---|
| 502 Bad Gateway | CDN〜オリジン間 | オリジンが不正なレスポンスを返した。プロセスがクラッシュしているなど |
| 503 Service Unavailable | オリジン自身 | オリジンが過負荷・停止中。意図的なメンテナンス時にも返す |
| 504 Gateway Timeout | CDN〜オリジン間 | オリジンが制限時間内に返答しなかった。処理が重い、DB待ちなど |
Cloudflareを挟んでいる場合、エラーページに「Cloudflareのロゴ」が出ているかどうかで、障害がCDN側かオリジン側かを大まかに判断できます。Cloudflare自身のエラーはエラーコードが Error 52x 等で表示されます。
インシデント発生時の初動対応についてはインシデントレポートを書く — 経営層向け障害報告のフォーマットも参照してください。
よく使うHTTPヘッダ
ステータスコードと並んでヘッダを読む力が重要です。代表的なものを整理します。
Content-Type
レスポンスのボディが何形式かを示します。
Content-Type: text/html; charset=utf-8
Content-Type: application/json
Content-Type: image/webp
ブラウザはこれを見てHTMLとして描画するか、JSONとして扱うか、画像として表示するかを判断します。APIのレスポンスで Content-Type: application/json を正しく返さないと、クライアントが誤動作することがあります。
Cache-Control
キャッシュの動作を指定します。最も重要なヘッダの一つです。
Cache-Control: public, max-age=3600
Cache-Control: no-store
Cache-Control: no-cache
Cache-Control: private, max-age=0
詳細は後述の「キャッシュ制御」で説明します。
ETag
リソースの「指紋」になる識別子です。コンテンツが変わると値が変わります。
ETag: "33a64df551425fcc55e4d42a148795d9f25f89d"
ブラウザが次回リクエストする際に If-None-Match ヘッダでこの値を送ると、サーバーは「変わっていない」と判断したとき 304 Not Modified を返し、ボディの再送を省略できます。
Location
リダイレクト先のURLを指定します。3xx系のレスポンスで使われます。
HTTP/1.1 301 Moved Permanently
Location: https://example.com/new-url/
Set-Cookie
サーバーがブラウザにCookieをセットするヘッダです。
Set-Cookie: session_id=abc123; Path=/; HttpOnly; Secure; SameSite=Strict
HttpOnly はJavaScriptからCookieを読めなくしてXSSリスクを下げます。Secure はHTTPS通信のみで送信します。CDNを挟む構成では、Cookieの有無がキャッシュ挙動に影響することに注意が必要です(Cookieが付くリクエストはデフォルトでキャッシュをバイパスすることが多い)。
キャッシュ制御 {#cache-control-detail}
キャッシュを適切に制御することで、サーバー負荷軽減とレスポンス高速化を両立できます。
Cache-Controlの主要ディレクティブ
| ディレクティブ | 意味 |
|---|---|
public | CDNを含むあらゆる中継キャッシュが保存可能 |
private | ブラウザのみキャッシュ可(CDNには保存しない) |
no-cache | キャッシュは持ってよいが、使う前にサーバーに有効性確認(再検証)が必要 |
no-store | キャッシュを一切保存しない |
max-age=秒数 | キャッシュが有効な秒数 |
s-maxage=秒数 | CDN(共有キャッシュ)向けの有効秒数。max-ageより優先 |
must-revalidate | 期限切れ後は必ずサーバーに確認。古いキャッシュをそのまま返してはいけない |
# 静的ファイル — 1年間CDNにキャッシュ
Cache-Control: public, max-age=31536000
# HTMLページ — CDNに1時間、ブラウザも1時間
Cache-Control: public, max-age=3600
# APIレスポンス — キャッシュしない
Cache-Control: no-store
# ログイン後ページ — ブラウザのみ・再検証必須
Cache-Control: private, no-cache
ETagと304 Not Modified
ETagを使った条件付きリクエストの流れは以下のとおりです。
1. 初回リクエスト
ブラウザ → GET /image.png
サーバー → 200 OK + ETag: "abc123" + 画像データ
2. 2回目リクエスト(キャッシュ期限切れ後)
ブラウザ → GET /image.png + If-None-Match: "abc123"
サーバー → 304 Not Modified(ボディなし)
3. コンテンツが変わっていた場合
サーバー → 200 OK + ETag: "xyz789" + 新しい画像データ
304 のレスポンスはボディを持たないため、ネットワーク転送量を大幅に削減できます。画像や大きなJSファイルで効果が顕著です。
Cloudflareのキャッシュ制御についてはCloudflareキャッシュをバイパスする方法で具体的な設定方法を解説しています。
301 vs 302 — リダイレクトの使い分け {#redirect-301-302}
301 Moved Permanently(恒久転送)
URLが永続的に変わった場合に使います。
- ブラウザは転送先URLを記憶し、次回から直接アクセスする
- Googleなどの検索エンジンはページランクを転送先に引き継ぐ
- 一度301でインデックスされると取り消しが難しい(ブラウザキャッシュが残る)
# 使う場面
- ドメイン移行(old.com → new.com)
- URLの恒久的な変更(/old-path/ → /new-path/)
- HTTPからHTTPSへの恒久転送
302 Found(一時転送)
URLが一時的に変わっている場合に使います。
- ブラウザは元のURLを記憶し続ける
- 検索エンジンはページランクを転送しない
- メンテナンスページへの一時転送に向いている
# 使う場面
- メンテナンス中の一時転送
- ABテスト中の振り分け
- ログイン後のリダイレクト(もとのURLに戻すため)
間違えると何が起きるか
本来301を使うべき場面で302を使うと、SEO上の評価が元URLに残り続けます。逆に、302にすべき一時転送に301を使うと、ブラウザがキャッシュするため後で「転送をやめたい」ときに戻せなくなります(ブラウザが元URLに来た瞬間にキャッシュから転送してしまう)。
HTTP/2とHTTP/3の概要
HTTP/1.1の仕組みを理解した上で、HTTP/2とHTTP/3が何を改善したかを押さえておきます。
HTTP/2(2015年標準化)
HTTP/1.1では、1つのTCP接続で1つのリクエストしか処理できないという制約がありました(複数接続を張ることで回避していたが非効率)。HTTP/2ではこれを改善しました。
| 機能 | 内容 |
|---|---|
| 多重化 | 1つのTCP接続で複数リクエストを並行処理 |
| ヘッダ圧縮 | HPACKアルゴリズムで重複ヘッダを圧縮(特に繰り返しリクエストで効果大) |
| サーバープッシュ | クライアントのリクエスト前にリソースを先行送信(現在はあまり使われない) |
Cloudflareはデフォルトでhttp/2に対応しており、HTTPS接続時に自動で有効になります。
HTTP/3(2022年RFC標準化)
HTTP/2はTCP上で動くため、パケットロスが起きると全ストリームが止まる問題(HOLブロッキング)がありました。HTTP/3はトランスポート層をTCPからUDP上のQUICに変更し、この問題を解消しています。
| 比較 | HTTP/2 | HTTP/3 |
|---|---|---|
| トランスポート | TCP | QUIC (UDP上) |
| HOLブロッキング | あり(TCPレベル) | なし(ストリームが独立) |
| 接続確立 | TCP+TLSで複数ラウンドトリップ | 0-RTT/1-RTTで高速化 |
| モバイル対応 | 接続切替時に再確立が必要 | 接続IDで継続維持 |
Cloudflareはhttp/3(QUIC)を「速度とパフォーマンス」設定から有効にできます。対応ブラウザではHTTP/3が自動選択され、非対応の場合はHTTP/2にフォールバックします。
CDNがHTTP/2・HTTP/3に対応していることで、エッジ〜ブラウザ間の通信が効率化されます。CDNの仕組みとの関係はCDNの仕組みと使いどころ — なぜCloudflareを挟むのかで解説しています。
まとめ
| 項目 | 覚えておくポイント |
|---|---|
| 2xx(成功) | 200が基本。201はリソース作成、204はボディなし成功 |
| 3xx(転送) | 301=恒久(SEO引継ぎ)、302=一時、304=キャッシュ有効で再送不要 |
| 4xx(クライアントエラー) | 401=未認証、403=権限なし、404=存在しない、429=レートリミット |
| 5xx(サーバーエラー) | 502=上流から不正レスポンス、503=サーバー停止中、504=上流タイムアウト |
| Cache-Control | public+max-ageでCDNキャッシュ、no-storeでキャッシュ禁止 |
| ETag + 304 | 差分のみ検証して転送量を削減する仕組み |
| 301 vs 302 | 恒久変更=301、一時変更=302。間違えるとSEOかブラウザキャッシュに影響 |
| 502/503/504 | CDNとオリジンのどの層でエラーが起きているかを判断する手がかり |
| HTTP/2 vs HTTP/3 | HTTP/2=TCP上の多重化、HTTP/3=QUIC上でHOLブロッキング解消 |
HTTPのステータスコードとヘッダを理解しておくと、CDNのキャッシュ設定やインシデント対応の根拠が明確になります。次のステップとして、以下の記事でより具体的な設定を確認してください。