HTTPとURL

目次

概要

HTTPは、Webブラウザ、APICDN、認証、キャッシュ、セキュリティをつなぐ共通の土台です。Webアプリケーションやクラウド配信を理解するには、まずURL、methodstatus codeheadercacheの役割をつかむと見通しがよくなります。

要点

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としてサーバーへ送られません。ブラウザがページ内移動などに使います。

flowchart LR URL["URL"] --> S["scheme"] URL --> H["host"] URL --> P["path"] URL --> Q["query"] URL --> F["fragment"]

HTTPの基本構造

HTTPはrequestとresponseのペアで動きます。

sequenceDiagram participant Browser participant Server Browser->>Server: GET /docs HTTP/1.1 Server-->>Browser: 200 OK + HTML

requestには、method、path、header、bodyが含まれます。responseには、status codeheader、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の状態」を覚えている前提で動かない、という意味です。

sequenceDiagram participant Client participant Server Client->>Server: Request 1 Server-->>Client: Response 1 Client->>Server: Request 2 Server-->>Client: Response 2

ただし、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上で動く、接続確立や損失耐性を改善

methodstatus codeheader、URIの意味はHTTP semanticsとして共有されます。したがって、まずはHTTP/1.1的なrequest/responseの形で理解し、その後にHTTP/2/3の性能上の違いを見ると学びやすいです。

flowchart TD Sem["HTTP semantics<br>method / status / header / cache"] --> H1["HTTP/1.1"] Sem --> H2["HTTP/2"] Sem --> H3["HTTP/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は、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 のように値の種類が非常に多いheaderVary に入れると、cache hit率が大きく下がることがあります。

cache

HTTP cacheは、同じresponseを再利用して高速化する仕組みです。ブラウザ、CDN、proxy、サーバーの各層で関わります。

flowchart LR B["Browser cache"] --> C["CDN cache"] C --> O["Origin server"]

代表的な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で考えます。

stateDiagram-v2 [*] --> Fresh: stored response Fresh --> Fresh: age < max-age Fresh --> Stale: age >= max-age Stale --> Fresh: validation returns 304 Stale --> Replaced: validation returns 200

共有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 更新時刻で確認
sequenceDiagram participant Browser participant Cache participant Origin Browser->>Cache: GET /index.html Cache->>Origin: If-None-Match: "abc" Origin-->>Cache: 304 Not Modified Cache-->>Browser: cached body

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が送られます。

sequenceDiagram participant Browser participant API Browser->>API: OPTIONS /items API-->>Browser: Access-Control-Allow-* Browser->>API: POST /items API-->>Browser: 201 Created

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の問題は、次の順に見ると切り分けやすいです。

  1. URLは正しいか
  2. methodは正しいか
  3. status codeは何か
  4. request headerは正しいか
  5. response headerは正しいか
  6. bodyは期待通りか
  7. cacheが古くないか
  8. 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で調べる

curlHTTPを調べる基本ツールです。

コマンド 用途
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-ControlETagAgeVia、CDN固有headerを確認します。

curl -I https://example.com/assets/app.css

API設計での見方

HTTPをAPI設計で使うときは、URL、methodstatus 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の知識が配信設計に直結します。

flowchart LR Browser["Browser"] --> CDN["CDN"] CDN --> Origin["S3 / Origin"] CDN --> Cache["edge cache"]

見るポイントです。

対象 確認すること
HTML cacheを短めにするか
CSS/JS fingerprint付きなら長期cacheできるか
画像 Content-Type は正しいか
clean URL /path/path/index.html に解決されるか
404 CDNとoriginのどちらが返しているか
redirect httpからhttps、wwwありなしの統一

curl -Iheaderを見ると、cacheやredirectを確認できます。

curl -I https://example.com/
curl -I https://example.com/assets/app.css

AccessDeniedNoSuchKey が見える場合、アプリケーションの問題ではなく、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) で優先度指定可能

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、methodstatus codeheadercache、cookie、CORSを理解すると、Webアプリケーション、API、CDN、認証、セキュリティの問題を同じ枠組みで調べられます。HTTP/2 の多重化、HTTP/3 の QUIC、キャッシュ戦略、CSP などの実装知識を組み合わせることで、セキュアでパフォーマントな Web システムを構築できます。

参考文献

公式・標準

MDN Web Docs

関連トピック

  • WebSocket Protocol (RFC 6455)
  • Server-Sent Events (EventSource API)
  • HTTP Signature Authentication