HTTPとURL
目次
- 概要
- URLを分解する
- HTTPの基本構造
- HTTPはstateless
- HTTPバージョンの見方
- method
- status code
- header
- content negotiation
- cache
- conditional request
- cookieとsession
- CORS
- セキュリティ系header
- デバッグの見方
- curlで調べる
- API設計での見方
- 静的サイト配信での見方
- トラブルシューティング表
- HTTPヘッダの深堀り
- HTTP Status コードの分類と意味
- Content Negotiation (RFC 9110)
- Cookie のセキュリティ
- URL エンコーディング
- HTTP/2 と HTTP/3 の進化
- ステータスコードの詳細分類
- Request/Response の実装パターン
- Rate Limiting ヘッダ
- Content-Type と Charset
- WebSocket と HTTP の関係
- Domain と Path の計画
- HTTP/2:多重化による高速化
- HTTP/3 と QUIC
- キャッシュの詳細戦略
- Content Security Policy(CSP)の実装
- まとめ
- 参考文献
概要
HTTPは、Webブラウザ、API、CDN、認証、キャッシュ、セキュリティをつなぐ共通の土台です。Webアプリケーションやクラウド配信を理解するには、まずURL、method、status code、header、cacheの役割をつかむと見通しがよくなります。
HTTPは「requestとresponseの約束」です。URLは場所、methodは意図、headerは追加情報、bodyは内容、status codeは結果を表します。
URLを分解する
URLは、単なる文字列ではなく、いくつかの部品からできています。
https://example.com:443/docs/index.html?q=cpu#section-1
| 部品 | 例 | 役割 |
|---|---|---|
| scheme | https |
通信方式 |
| host | example.com |
接続先 |
| port | 443 |
接続先ポート |
| path | /docs/index.html |
サーバー上の対象 |
| query | q=cpu |
追加の検索条件 |
| fragment | section-1 |
クライアント側の位置指定 |
fragmentは通常、HTTP requestとしてサーバーへ送られません。ブラウザがページ内移動などに使います。
HTTPの基本構造
HTTPはrequestとresponseのペアで動きます。
requestには、method、path、header、bodyが含まれます。responseには、status code、header、bodyが含まれます。
GET /docs HTTP/1.1
Host: example.com
Accept: text/html
HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
Cache-Control: max-age=3600
HTTPはstateless
RFC 9110では、HTTPは分散されたハイパーテキスト情報システムのためのstatelessなapplication-level protocolとして定義されています。statelessとは、protocol自体が「前のrequestの状態」を覚えている前提で動かない、という意味です。
ただし、Webアプリケーションに状態がないわけではありません。ログイン状態、カート、CSRF token、rate limitなどは、cookie、session store、token、databaseなどを組み合わせて作ります。
| 状態の持ち方 | 例 | 注意 |
|---|---|---|
| cookie | session id | HttpOnly, Secure, SameSite |
| bearer token | API token, JWT | 漏えい時の失効、期限 |
| server session | Redis, DB | スケール、期限切れ |
| cache | browser, CDN | private/sharedの区別 |
statelessという性質を理解すると、なぜ各requestにcookieやAuthorization headerが付くのか、なぜCDNがresponseを再利用できるのかが見えやすくなります。
HTTPバージョンの見方
HTTPは複数のバージョンがありますが、アプリケーション開発者がまず見るべき意味は「semanticsは大きく共通し、転送の仕組みが進化している」という点です。
| バージョン | 見方 |
|---|---|
| HTTP/1.1 | テキスト形式、connection reuse、広く普及 |
| HTTP/2 | binary framing、多重化、header圧縮 |
| HTTP/3 | QUIC/UDP上で動く、接続確立や損失耐性を改善 |
method、status code、header、URIの意味はHTTP semanticsとして共有されます。したがって、まずはHTTP/1.1的なrequest/responseの形で理解し、その後にHTTP/2/3の性能上の違いを見ると学びやすいです。
method
methodは、requestの意図を表します。
| method | 典型用途 |
|---|---|
GET |
取得 |
POST |
作成、送信、処理 |
PUT |
全体の置き換え |
PATCH |
部分更新 |
DELETE |
削除 |
HEAD |
headerだけ取得 |
OPTIONS |
利用可能な通信方法の確認 |
GET は安全で冪等であることが期待されます。安全とは、読み取り目的で副作用を持たないことです。冪等とは、同じrequestを複数回送っても結果が変わらないことです。
| method | safe | idempotent |
|---|---|---|
| GET | yes | yes |
| POST | no | no |
| PUT | no | yes |
| DELETE | no | yes |
実務では、retry、cache、二重送信対策に関わります。
status code
status codeはresponseの結果です。
| 範囲 | 意味 |
|---|---|
| 1xx | 処理中 |
| 2xx | 成功 |
| 3xx | リダイレクト |
| 4xx | クライアント側の問題 |
| 5xx | サーバー側の問題 |
よく見るcodeです。
| code | 意味 |
|---|---|
| 200 | OK |
| 201 | Created |
| 204 | No Content |
| 301 | Moved Permanently |
| 302 | Found |
| 304 | Not Modified |
| 400 | Bad Request |
| 401 | Unauthorized |
| 403 | Forbidden |
| 404 | Not Found |
| 429 | Too Many Requests |
| 500 | Internal Server Error |
| 502 | Bad Gateway |
| 503 | Service Unavailable |
401 は認証が必要、403 は認証済みでも権限がない、という違いで理解するとよいです。
header
headerは、requestやresponseに付く追加情報です。
| header | 役割 |
|---|---|
Content-Type |
bodyの形式 |
Accept |
受け取りたい形式 |
Authorization |
認証情報 |
Cache-Control |
キャッシュ制御 |
ETag |
内容の識別子 |
Set-Cookie |
cookie設定 |
Origin |
CORSで使う送信元 |
bodyがJSONなら Content-Type: application/json を付けます。
POST /api/items HTTP/1.1
Content-Type: application/json
{"name":"book"}
content negotiation
HTTPでは、クライアントが「どの表現を受け取りたいか」をrequest headerで伝え、サーバーがresponseを選ぶことがあります。これをcontent negotiationと呼びます。
| header | 意味 |
|---|---|
Accept |
受け取りたいmedia type |
Accept-Language |
希望する言語 |
Accept-Encoding |
受け取れる圧縮方式 |
Content-Type |
送信するbodyの形式 |
例です。
GET /articles/1 HTTP/1.1
Accept: application/json
Accept-Language: ja
同じURLでもheaderによってresponseが変わる場合、cacheには Vary が重要になります。
Vary: Accept-Language
Vary は「このheaderの値もcache keyに含めて区別する」という合図です。便利ですが、User-Agent のように値の種類が非常に多いheaderを Vary に入れると、cache hit率が大きく下がることがあります。
cache
HTTP cacheは、同じresponseを再利用して高速化する仕組みです。ブラウザ、CDN、proxy、サーバーの各層で関わります。
代表的なheaderです。
| header | 意味 |
|---|---|
Cache-Control: max-age=3600 |
3600秒は新鮮とみなす |
Cache-Control: no-store |
保存しない |
ETag |
内容の識別子 |
If-None-Match |
ETagが同じなら304を返せる |
静的サイトでは、HTMLは短め、CSS/JS/画像はfingerprint付きで長めにcacheする設計がよく使われます。
cacheの状態は、freshとstaleで考えます。
共有cache(CDNなど)とprivate cache(ブラウザcache)は分けて考えます。ログインユーザー固有のresponseを共有cacheに載せると、情報漏えいにつながる可能性があります。
| response | cache方針 |
|---|---|
| ユーザー固有のHTML | private または no-store |
| fingerprint付きCSS/JS | 長い max-age, immutable |
| APIの個人情報 | 基本は no-store を検討 |
| 公開画像 | CDNで長めにcache |
conditional request
HTTP cacheでは、古くなったresponseをすぐ捨てるのではなく、originに「変わったか」を確認できます。これがconditional requestです。
代表的なvalidatorです。
| response header | request header | 役割 |
|---|---|---|
ETag |
If-None-Match |
内容識別子で確認 |
Last-Modified |
If-Modified-Since |
更新時刻で確認 |
304 Not Modified はbodyを返さず、「保存済みのresponseを再利用してよい」と伝えます。静的ファイルではETagやLast-Modifiedを適切に使うと、転送量を減らしつつ更新確認ができます。
cookieとsession
cookieは、ブラウザが保存し、同じサイトへのrequestに付ける小さなデータです。
Set-Cookie: session=abc; HttpOnly; Secure; SameSite=Lax
| 属性 | 意味 |
|---|---|
HttpOnly |
JavaScriptから読めない |
Secure |
HTTPSのみで送る |
SameSite |
cross-site requestでの送信を制御 |
Max-Age |
有効期間 |
session IDをcookieに入れ、実際のsession情報はサーバー側に置く設計がよく使われます。
CORS
CORSは、ブラウザが異なるoriginへのrequestを制御する仕組みです。
originは、scheme、host、portの組み合わせです。
https://example.com:443
別originへrequestするとき、ブラウザはresponse headerを見て許可されているか判断します。
Access-Control-Allow-Origin: https://app.example.com
preflightが必要なrequestでは、事前に OPTIONS requestが送られます。
CORSはサーバー間通信の制限ではなく、ブラウザの安全機構です。
よくある誤解です。
| 誤解 | 実際 |
|---|---|
| CORSはAPIサーバーを守る仕組み | 主にブラウザが読み取りを制御する仕組み |
| curlで通るならブラウザでも通る | ブラウザはCORSを適用する |
* にすれば常に解決 |
credentials付きrequestでは使えない |
| preflightは無駄 | 危険になり得るcross-origin requestの事前確認 |
credentials(cookieやAuthorization header)を含むcross-origin requestでは、Access-Control-Allow-Origin を具体的なoriginにし、Access-Control-Allow-Credentials: true を使う必要があります。
セキュリティ系header
HTTP headerはセキュリティにも関わります。Webセキュリティの本編ほど深くは扱いませんが、代表的なものは知っておくとデバッグに役立ちます。
| header | 役割 |
|---|---|
Content-Security-Policy |
script, style, imageなどの読み込み元を制限 |
Strict-Transport-Security |
HTTPS接続を強制 |
X-Content-Type-Options: nosniff |
MIME sniffingを抑制 |
Referrer-Policy |
Refererの送信範囲を制御 |
Permissions-Policy |
ブラウザ機能の利用範囲を制御 |
CSPは強力ですが、設定を誤るとscriptやstyleが動かなくなります。まずreport-onlyで観察し、段階的に強める方法もあります。
Content-Security-Policy: default-src 'self'; img-src 'self' https:
デバッグの見方
HTTPの問題は、次の順に見ると切り分けやすいです。
- URLは正しいか
- methodは正しいか
- status codeは何か
- request headerは正しいか
- response headerは正しいか
- bodyは期待通りか
- cacheが古くないか
- redirectが挟まっていないか
curl ではheaderを確認できます。
curl -I https://example.com
curl -v https://example.com
ブラウザではDevToolsのNetwork tabを見ます。特に、status、method、request header、response header、initiator、timingが重要です。
curlで調べる
curl はHTTPを調べる基本ツールです。
| コマンド | 用途 |
|---|---|
curl -I URL |
response headerだけ見る |
curl -v URL |
request/responseの詳細を見る |
curl -L URL |
redirectを追う |
curl -H 'Accept: application/json' URL |
headerを指定 |
curl -X POST -d ... URL |
method/bodyを指定 |
例です。
curl -I https://example.com/
curl -v https://example.com/api/items
curl -H 'Accept: application/json' https://example.com/api/items
cacheを見るときは、Cache-Control、ETag、Age、Via、CDN固有headerを確認します。
curl -I https://example.com/assets/app.css
API設計での見方
HTTPをAPI設計で使うときは、URL、method、status code、bodyの責務を混ぜないようにします。
| 設計対象 | 置く情報 |
|---|---|
| URL path | resourceの場所 |
| method | 操作の意図 |
| query | 絞り込み、並び替え、ページング |
| request body | 作成・更新する内容 |
| status code | 結果 |
| response body | 結果の詳細 |
例です。
GET /articles?tag=network&page=2
POST /articles
Content-Type: application/json
{"title":"HTTP notes","body":"..."}
避けたい例です。
GET /createArticle?title=HTTP
GET は取得のためのmethodなので、作成のような副作用を持つ操作には向きません。cacheやcrawler、retryの挙動と衝突しやすくなります。
APIのエラーresponseでは、機械が判定できるcodeと、人間が読めるmessageを分けると扱いやすくなります。
{
"error": {
"code": "validation_failed",
"message": "title is required",
"fields": {
"title": "required"
}
}
}
静的サイト配信での見方
静的サイトでは、HTTPの知識が配信設計に直結します。
見るポイントです。
| 対象 | 確認すること |
|---|---|
| HTML | cacheを短めにするか |
| CSS/JS | fingerprint付きなら長期cacheできるか |
| 画像 | Content-Type は正しいか |
| clean URL | /path が /path/index.html に解決されるか |
| 404 | CDNとoriginのどちらが返しているか |
| redirect | httpからhttps、wwwありなしの統一 |
curl -I でheaderを見ると、cacheやredirectを確認できます。
curl -I https://example.com/
curl -I https://example.com/assets/app.css
AccessDenied や NoSuchKey が見える場合、アプリケーションの問題ではなく、CDNからoriginへのpath解決や権限設定の問題であることがあります。status codeだけでなく、どの層が返しているresponseかを見るのが大切です。
トラブルシューティング表
| 症状 | 見る場所 | よくある原因 |
|---|---|---|
| 404 | URL, routing, origin path | path違い、clean URL未対応 |
| 403 | auth, IAM, bucket policy | 権限不足、署名不一致 |
| 500 | server log | 例外、設定不足 |
| 502 | proxy/CDN log | upstream失敗、TLS、origin unreachable |
| CORS error | browser console, response header | Access-Control-Allow-Origin 不足 |
| 古いCSSが残る | cache header, CDN | 長期cache、invalidation不足 |
| POSTが二重実行 | retry, form submit | 冪等性なし、二重送信対策不足 |
| cookieが送られない | DevTools, Set-Cookie | SameSite, Secure, domain/path |
HTTPの調査では、「ブラウザが表示したエラー」だけで判断しません。Network tab、response header、server log、CDN logを合わせて、どの層で失敗したかを切り分けます。
HTTPヘッダの深堀り
RFC 9110での重要ヘッダ
RFC 9110 (HTTP Semantics, 2022) では、以下のヘッダが規定:
リクエストヘッダ
Host: example.com (必須、ホスト指定)
User-Agent: Mozilla/5.0 (クライアント識別)
Accept: application/json (欲しいメディアタイプ)
Accept-Language: ja-JP (優先言語)
Authorization: Bearer ... (認証情報)
Referer: https://... (遷移元、セキュリティに注意)
レスポンスヘッダ
Content-Type: application/json (メディアタイプ)
Content-Length: 1024 (ボディサイズ)
Cache-Control: max-age=3600 (キャッシュ指示)
Set-Cookie: sid=abc; SameSite=Strict (クッキー設定)
ETag: "33a64df..." (リソース識別子)
Last-Modified: Mon, 12 Jan 2024 12:00:00 GMT
Location: https://example.com/new (リダイレクト先)
Access-Control-Allow-Origin: * (CORS許可)
セキュリティ関連ヘッダ
X-Content-Type-Options: nosniff (MIME sniffing 防止)
X-Frame-Options: DENY (Clickjacking 防止)
Content-Security-Policy: default-src 'self' (CSP, XSS/Injection 防止)
Strict-Transport-Security: max-age=31536000 (HSTS, HTTPS 強制)
Referrer-Policy: strict-origin-when-cross-origin (Referer 制御)
これらは RFC 7230-7235 および各種セキュリティドラフトで定義。
HTTP Status コードの分類と意味
RFC 9110 での完全な分類:
1xx Information (Informational)
100 Continue (クライアントが続行してよい)
101 Switching Protocols (プロトコル切り替え)
2xx Success
200 OK (成功)
201 Created (リソース作成)
204 No Content (成功だが body なし)
3xx Redirection
301 Moved Permanently (永続的移動、SEO上 old URL は削除)
302 Found (一時的移動)
304 Not Modified (キャッシュ有効)
307/308 (method 保持リダイレクト)
4xx Client Error
400 Bad Request (リクエスト不正)
401 Unauthorized (認証不足)
403 Forbidden (認可不足)
404 Not Found (リソース不在)
409 Conflict (更新競合)
429 Too Many Requests (Rate limit)
5xx Server Error
500 Internal Server Error
502 Bad Gateway (proxy/upstream 失敗)
503 Service Unavailable (一時的)
504 Gateway Timeout (upstream タイムアウト)
キャッシュ戦略 (RFC 9111)
Cache-Control のディレクティブ:
public (公開キャッシュ可)
private (private キャッシュのみ)
max-age=3600 (秒単位の有効期限)
s-maxage=86400 (shared cache の有効期限)
no-cache (検証なしで再利用不可)
no-store (キャッシュ保存禁止)
must-revalidate (期限切れで再検証必須)
stale-while-revalidate=86400 (期限後も使用可、バグで再検証)
例:
# HTML: 毎回検証
Cache-Control: public, max-age=0, must-revalidate
# CSS/JS (fingerprint): 長期キャッシュ
Cache-Control: public, max-age=31536000, immutable
# API: キャッシュなし
Cache-Control: no-store
Content Negotiation (RFC 9110)
クライアントとサーバーが合意して、最適なメディアタイプを決める:
リクエスト:
Accept: application/json, text/html;q=0.9
サーバーレスポンス:
Content-Type: application/json
品質係数 (q=0.9) で優先度指定可能
Cookie のセキュリティ
Set-Cookie ヘッダの重要な属性:
Set-Cookie: sessionid=abc123;
Path=/; (パス制限)
Domain=.example.com; (ドメイン制限)
Expires=Wed, 09 Jun 2024 10:18:14 GMT;
Max-Age=3600; (有効期限)
Secure; (HTTPS only)
HttpOnly; (JavaScript access 禁止)
SameSite=Strict (CSRF 防止)
SameSite 値:
- Strict: クロスサイト要求で送らない
- Lax: トップレベルナビゲーション(リンククリック)のみ送信
- None; Secure: すべてで送信(HTTPS 必須)
URL エンコーディング
URL に含める特殊文字はパーセントエンコーディング:
スペース → %20
! → %21
# → %23
& → %26
+ → %2B
= → %3D
日本語 → UTF-8 バイト列をエンコード
query string の解析時に注意:
/path?key=val&key2=val2
→ { key: "val", key2: "val2" }
/path?key=a%20b
→ { key: "a b" }
/path?key=&key2=
→ { key: "", key2: "" } or { key: undefined }
HTTP/2 と HTTP/3 の進化
HTTP/2 (RFC 7540)
HTTP/1.1 の課題(複数接続、line-of-blocking)を解決:
HTTP/1.1: 複数リソース取得に複数接続が必要
GET /index.html
GET /style.css
GET /script.js
HTTP/2: 単一接続でmultiplexing
HEADERS /index.html
HEADERS /style.css
HEADERS /script.js
→ すべて1接続で同時送信
HTTP/2 の利点:
| 機能 | 効果 |
|---|---|
| multiplexing | 接続数削減、並列転送 |
| server push | クライアント要求待たずに送信 |
| header compression | HPACK で圧縮 |
| binary framing | テキストより効率的 |
HTTP/3 と QUIC (RFC 9000)
UDP ベースで接続確立が高速:
TCP (HTTP/1.1/2):
Client → SYN
Server → SYN-ACK
Client → ACK
[connection established]
(3-way handshake: 1-RTT)
QUIC (HTTP/3):
Client → Initial packet (with TLS 1.3)
Server → Initial response
[connection established]
(0-RTT から 1-RTT に短縮)
実装例(curl でのプロトコル選択):
# HTTP/1.1
curl https://example.com
# HTTP/2 を強制
curl --http2 https://example.com
# HTTP/3 を試す
curl --http3 https://example.com
ステータスコードの詳細分類
1xx: Informational
| コード | 用途 |
|---|---|
| 100 Continue | クライアント待機(リクエスト本体の送信確認) |
| 101 Switching Protocols | プロトコル切り替え(WebSocket) |
2xx: Success
| コード | 用途 |
|---|---|
| 200 OK | 標準的な成功 |
| 201 Created | リソース作成成功(POST) |
| 202 Accepted | リクエスト受け入れ、非同期処理中 |
| 204 No Content | 成功、レスポンス本体なし |
| 206 Partial Content | 部分的なコンテンツ(Range request) |
3xx: Redirection
| コード | 用途 |
|---|---|
| 301 Moved Permanently | 永続的リダイレクト(SEO的に URL 変更) |
| 302 Found | 一時的リダイレクト |
| 304 Not Modified | キャッシュ有効(条件付きGET) |
| 307 Temporary Redirect | 302と同じだが、method 変わらない |
4xx: Client Error
| コード | 用途 | 例 |
|---|---|---|
| 400 Bad Request | 不正なリクエスト | JSONパース失敗 |
| 401 Unauthorized | 認証必須 | ログインが必要 |
| 403 Forbidden | 認可なし | 権限不足 |
| 404 Not Found | リソース未存在 | ページがない |
| 409 Conflict | 状態衝突 | 重複キー、同時編集 |
| 429 Too Many Requests | レート制限超過 | API呼び出し多すぎ |
5xx: Server Error
| コード | 用途 |
|---|---|
| 500 Internal Server Error | 予期しない実行時エラー |
| 502 Bad Gateway | アップストリーム無応答 |
| 503 Service Unavailable | 一時的に利用不可 |
| 504 Gateway Timeout | アップストリームタイムアウト |
Request/Response の実装パターン
RESTful API レスポンス設計
// 成功 (200)
{
"status": "success",
"data": {
"id": 1,
"name": "example"
}
}
// エラー (400)
{
"status": "error",
"code": "INVALID_INPUT",
"message": "Name is required",
"details": {
"field": "name",
"reason": "empty"
}
}
// リスト + ページング (200)
{
"status": "success",
"data": [...],
"pagination": {
"page": 1,
"per_page": 20,
"total": 100,
"pages": 5
}
}
CORS プリフライト リクエスト
OPTIONS /api/users HTTP/1.1
Host: api.example.com
Origin: https://client.example.com
Access-Control-Request-Method: POST
Access-Control-Request-Headers: Content-Type
→ サーバーの応答
Access-Control-Allow-Origin: https://client.example.com
Access-Control-Allow-Methods: GET, POST, PUT, DELETE
Access-Control-Allow-Headers: Content-Type
Access-Control-Max-Age: 86400
Rate Limiting ヘッダ
API のレート制限を クライアントに通知:
X-RateLimit-Limit: 100 (1時間あたりの上限)
X-RateLimit-Remaining: 42 (残り呼び出し数)
X-RateLimit-Reset: 1714012800 (制限リセット時刻、Unix時間)
Retry-After: 300 (秒数またはHTTP-date)
クライアント実装例(Python):
import requests
import time
def call_api(url):
response = requests.get(url)
if response.status_code == 429:
retry_after = int(response.headers.get('Retry-After', 60))
print(f"Rate limited. Retrying after {retry_after}s...")
time.sleep(retry_after)
return call_api(url)
return response.json()
Content-Type と Charset
API のレスポンスで重要な指定:
Content-Type: application/json; charset=utf-8
Content-Type: text/html; charset=utf-8
Content-Type: text/plain; charset=iso-8859-1
Content-Type: application/pdf
Content-Type: image/png
ブラウザでの fallback:
- charset がない場合、BOM(Byte Order Mark)から判定
- BOM もない場合、親リソースの charset を参照
- いずれもない場合、ASCII と仮定(結果として mojibake の可能性)
WebSocket と HTTP の関係
WebSocket は HTTP upgrade 経由で開始:
HTTP request:
GET /chat HTTP/1.1
Host: example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Sec-WebSocket-Version: 13
HTTP response:
101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
[WebSocket フレーム通信へ]
HTTP と WebSocket の使い分け:
| プロトコル | 特性 | 用途 |
|---|---|---|
| HTTP | Request/Response 同期 | 一般的な Web API |
| WebSocket | Bidirectional 非同期 | チャット、リアルタイム通知 |
| Server-Sent Events (SSE) | Server → Client ストリーム | サーバーサイド 通知 |
| gRPC | HTTP/2 双方向 | マイクロサービス RPC |
Domain と Path の計画
実務でのURL 構造設計パターン:
// RESTful API
/api/v1/users GET: ユーザーリスト
/api/v1/users/{id} GET: ユーザー詳細
/api/v1/users POST: ユーザー作成
/api/v1/users/{id} PUT: ユーザー更新
/api/v1/users/{id} DELETE: ユーザー削除
// リソース関連
/api/v1/users/{id}/posts GET: ユーザーの投稿
/api/v1/users/{id}/posts/{pid} GET: 特定投稿
// アクション
/api/v1/users/{id}/password-reset POST: パスワードリセット
/api/v1/users/{id}/confirm-email POST: メール確認
HTTP/2:多重化による高速化
HTTP/1.1 の大きな問題は「リクエスト待機」。1 つのコネクションで同時に 1 リクエストのみ。
HTTP/1.1:
GET /page.html [待機]
GET /style.css [待機] ← CSS がロード完了まで待つ
GET /script.js [待機]
HTTP/2 (Multiplexing):
GET /page.html
GET /style.css [同時並行]
GET /script.js
HTTP/2 の主要機能
1. バイナリフレーミング
HTTP/1.1 は テキストベース(人間が読める)。HTTP/2 はバイナリ(効率的)。
HTTP/1.1:
GET / HTTP/1.1\r\n
Host: example.com\r\n
...
HTTP/2:
[フレームタイプ][フラグ][ストリーム ID][ペイロード]
より小さく、パースも高速
2. ストリーム多重化
1 つの TCP コネクションで複数のリクエストを同時実行。
TCP Connection 1
├─ Stream 1: GET /index.html
├─ Stream 3: GET /style.css
└─ Stream 5: GET /app.js
全ストリームが同じ TCP を共有
3. サーバプッシュ
クライアントが要求せずにサーバがリソースを送信。
クライアント: GET /index.html
サーバ:
- /index.html を送信
- /style.css もプッシュ(index.html が style.css を使うから)
- /app.js もプッシュ
ブラウザはすぐにロード開始
4. ヘッダ圧縮(HPACK)
HTTP リクエストヘッダは重複が多い(User-Agent、Host など)。HPACK で圧縮。
Request 1:
Host: example.com
User-Agent: Mozilla/5.0
Cookie: sessionid=abc123
Request 2:
Host: example.com [圧縮:前回と同じ、差分のみ送信]
User-Agent: Mozilla/5.0 [圧縮:前回と同じ]
Cookie: sessionid=abc123 [圧縮:新規値のみ]
HTTP/2 の実装効果
HTTP/1.1:
複数コネクション(TCP overhead)
GET /page.html 150ms
GET /style.css 300ms(コネクション待機)
GET /script.js 450ms
HTTP/2(1 コネクション):
GET /page.html 150ms
GET /style.css 160ms(同時)
GET /script.js 170ms(同時)
合計:HTTP/1.1 = 450ms → HTTP/2 = 170ms(2.6 倍高速化)
HTTP/3 と QUIC
HTTP/3 は TCP の代わりに UDP ベースの QUIC プロトコルを使用。
QUIC の利点
1. 接続確立の高速化
TCP 3-way handshake + TLS 2-way handshake:
SYN -> SYN-ACK -> ACK -> TLS ClientHello -> TLS ServerHello -> ...
[複数往復で 100ms+]
QUIC 0-RTT:
以前の接続情報をキャッシュして即座に通信開始
[ほぼ遅延なし]
2. パケット損失への対応
TCP では 1 パケット損失で全体が待機(Head-of-Line blocking)。QUIC は独立したストリーム。
TCP:
Stream 1 [███████ ✗ ______] ← 1 パケット損失で待機
Stream 2 [█████████ ... 待機中
QUIC:
Stream 1 [███████ ✗ ______] ← 送信側が再送
Stream 2 [█████████ 続行] ← 継続(独立)
3. 接続移行(Connection Migration)
Wi-Fi → LTE に切り替わっても接続を維持。TCP では再接続が必要。
Wi-Fi (IP A) -> LTE (IP B)
TCP: 接続ロスト → 再接続(100ms+)
QUIC: 接続ID で識別 → シームレス切り替え
HTTP/3 現状
- Chrome, Firefox, Safari が対応
- Cloudflare, Google など大手 CDN が有効化
- 本格普及は 2024 以降
キャッシュの詳細戦略
Web パフォーマンスの 80% はキャッシュで決まる。
Etag(Entity Tag)による検証
リソースの「バージョン」を识别。クライアントが前回取得したバージョンと変わったかを確認。
初回リクエスト:
GET /api/user/123
Response 200:
Content: {"name": "Alice"}
ETag: "abc123def"
次回リクエスト(キャッシュあり):
GET /api/user/123
If-None-Match: "abc123def"
サーバの応答:
- ETag が一致 → 304 Not Modified(キャッシュ使用)
- ETag が異なる → 200 OK with new content
キャッシュ戦略の分類
| リソース | Cache-Control | 理由 |
|---|---|---|
| HTML | max-age=3600 | ページ更新は数時間程度 |
| CSS | max-age=31536000 | ファイル名にハッシュを含める(a.12345.css) |
| JS | max-age=31536000 | CSS 同様 |
| 画像 | max-age=31536000 | 頻繁に変わらない |
| API JSON | max-age=0 | 常に最新 |
| ユーザプロファイル | max-age=60 | 1 分程度の遅延は許容 |
Vary ヘッダによる条件付きキャッシュ
同じ URL でも条件によって異なる応答。
レスポンス:
Vary: Accept-Encoding, User-Agent
含意:
- Accept-Encoding が異なる → 異なるキャッシュエントリ
- User-Agent が異なる → 異なるキャッシュエントリ
(モバイル版とデスクトップ版を分ける)
Content Security Policy(CSP)の実装
XSS(Cross-Site Scripting)攻撃を防ぐため、どのスクリプトが実行可能か指定。
Content-Security-Policy: default-src 'self'; script-src 'self' https://cdn.example.com; style-src 'self' 'unsafe-inline'
説明:
- default-src 'self': すべてのリソースは同一オリジンのみ
- script-src 'self' https://cdn.example.com: スクリプトは同一オリジンか指定 CDN
- style-src 'self' 'unsafe-inline': CSS は同一オリジンかインライン(非推奨だが許可)
CSP レポート
違反が発生したときにサーバに報告:
Content-Security-Policy: default-src 'self'; report-uri https://csp-report.example.com/report
違反例:
スクリプト <script src="https://evil.com/malware.js"></script> を読み込もうとした
→ ブロック
→ POST https://csp-report.example.com/report に JSON で報告
まとめ
HTTPは、Webの共通語です。URL、method、status code、header、cache、cookie、CORSを理解すると、Webアプリケーション、API、CDN、認証、セキュリティの問題を同じ枠組みで調べられます。HTTP/2 の多重化、HTTP/3 の QUIC、キャッシュ戦略、CSP などの実装知識を組み合わせることで、セキュアでパフォーマントな Web システムを構築できます。
参考文献
公式・標準
- RFC 9110: HTTP Semantics
- RFC 9111: HTTP Caching
- RFC 7540: HTTP/2
- RFC 9000: QUIC: A UDP-Based Multiplexed and Secure Transport
MDN Web Docs
- MDN Web Docs: Content-Security-Policy
- MDN Web Docs: CORS
- MDN Web Docs: HTTP
- MDN Web Docs: HTTP caching
- MDN Web Docs: HTTP request methods
- MDN Web Docs: HTTP response status codes
- MDN Web Docs: Set-Cookie
- MDN Web Docs: URI
関連トピック
- WebSocket Protocol (RFC 6455)
- Server-Sent Events (EventSource API)
- HTTP Signature Authentication