メインコンテンツへ移動
SEMentor
ネットワーク 約10分

CORSとHTTPヘッダーの仕組み

フロントエンド開発でよく遭遇するCORSエラーの原因と解決策、および重要なHTTPヘッダーの役割を体系的に理解する

「CORSエラー」は何が起きているのか

フロントエンド開発をしていると、ブラウザのコンソールにこのエラーが表示されることがあります。

Access to XMLHttpRequest at 'https://api.example.com/data'
from origin 'http://localhost:3000' has been blocked by CORS policy

このエラーは、ブラウザが**同一オリジンポリシー(Same-Origin Policy)**を守った結果です。まずはこの大元の仕組みを理解するところから始めます。

同一オリジンポリシー

ブラウザはセキュリティ上の理由から、異なるオリジンへのリクエストを制限しています。

オリジンとは「プロトコル + ドメイン + ポート番号」の組み合わせです。

URL比較対象(http://example.com:80)同一オリジン?
http://example.com/pageポート省略(80と同じ)✅ 同一
https://example.comプロトコルが違う❌ 異なる
http://api.example.comサブドメインが違う❌ 異なる
http://example.com:8080ポートが違う❌ 異なる

この制限がないと、悪意あるサイトが別サービスのAPIを呼び出して、ログイン中ユーザーのデータを盗めてしまいます。

CORS(Cross-Origin Resource Sharing)

CORS は「サーバーが明示的に許可したオリジンからのクロスオリジンリクエストを通す」仕組みです。禁止を緩和する仕組みではなく、サーバーの意図を表明する仕組みです。

シンプルリクエスト

GETPOST(Content-Type が application/x-www-form-urlencoded など)の場合、ブラウザはリクエストを直接送り、レスポンスの Access-Control-Allow-Origin ヘッダーを確認します。

# リクエスト
GET /data HTTP/1.1
Origin: http://localhost:3000

# レスポンス(サーバーが許可する場合)
Access-Control-Allow-Origin: http://localhost:3000

プリフライトリクエスト

PUT / DELETE / PATCHContent-Type: application/json のリクエストでは、ブラウザが本番リクエストの前に**プリフライト(OPTIONSメソッド)**を送ります。

# プリフライト
OPTIONS /api/users HTTP/1.1
Origin: http://localhost:3000
Access-Control-Request-Method: PUT
Access-Control-Request-Headers: Content-Type

# サーバーの応答
Access-Control-Allow-Origin: http://localhost:3000
Access-Control-Allow-Methods: GET, POST, PUT, DELETE
Access-Control-Allow-Headers: Content-Type
Access-Control-Max-Age: 86400  # キャッシュ秒数

プリフライトが失敗(サーバーが許可しない)した場合、本番リクエストは送信されません。

CORSエラーの解決策

CORSエラーはサーバー側で設定を追加することで解決します。フロントエンドだけでは解決できません。

Express.js(Node.js)の例:

const cors = require('cors');

app.use(cors({
  origin: ['http://localhost:3000', 'https://yourdomain.com'],
  methods: ['GET', 'POST', 'PUT', 'DELETE'],
  allowedHeaders: ['Content-Type', 'Authorization'],
  credentials: true,  // Cookie送信を許可する場合
}));

注意点: Access-Control-Allow-Origin: *(ワイルドカード)は credentials: true と組み合わせられません。Cookie や認証情報を送る場合は、オリジンを明示する必要があります。

重要なHTTPヘッダー

CORS以外にも、Web開発で頻繁に登場するHTTPヘッダーを押さえておきます。

リクエストヘッダー(クライアント→サーバー)

ヘッダー役割
Authorization認証情報の送信Bearer eyJhbGci...
Content-Typeリクエストボディの形式application/json
Accept受け入れるレスポンス形式application/json
Cookieセッション情報などsession_id=abc123

レスポンスヘッダー(サーバー→クライアント)

ヘッダー役割
Content-Typeレスポンスの形式(text/html, application/json など)
Cache-Controlキャッシュの制御(no-cache, max-age=3600 など)
Set-CookieクライアントにCookieを設定
Locationリダイレクト先URL(301/302と組み合わせ)

セキュリティ関連のレスポンスヘッダー

ヘッダー役割
Strict-Transport-SecurityHTTPSを強制(HSTS)
Content-Security-Policyスクリプト・スタイルの読み込み元を制限(XSS対策)
X-Content-Type-Options: nosniffMIMEタイプのスニッフィングを禁止
X-Frame-Options: DENYiframeへの埋め込みを禁止(クリックジャッキング対策)

本番環境のWebアプリでは、これらのセキュリティヘッダーを適切に設定することが重要です。

まとめ

概念ひと言まとめ
同一オリジンポリシーブラウザが異なるオリジンへのアクセスを制限する仕組み
CORSサーバーが特定オリジンを許可することで制限を緩和する仕組み
プリフライト非シンプルリクエスト前にブラウザが送るOPTIONS確認
CORSエラーの解決サーバー側で Access-Control-Allow-Origin を設定する

CORSエラーに遭遇したとき、「ブラウザがサーバーの許可を確認している」と理解していれば、冷静に原因を特定できます。解決策はサーバーの設定変更です。


HTTPの基礎についてはHTTPとHTTPSの仕組みで学べます。

このレッスンは未完了です。