13
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

CORSとプリフライトリクエストについて

13
Last updated at Posted at 2026-04-04

はじめに

CORS(Cross-Origin Resource Sharing)やプリフライトリクエストについてハマったのでその辺をまとめておきます。

CORSとは

オリジンとは

オリジンとは、以下の3つの組み合わせです。

要素
スキーム(プロトコル) https://
ホスト(ドメイン) api.example.com
ポート番号 :443

3つがすべて一致する場合のみ「同一オリジン」です。1つでも違えば「異なるオリジン」になります。

URL https://app.example.com との関係
https://app.example.com/about ✅ 同一オリジン(パスが違うだけ)
https://api.example.com ❌ 異なるオリジン(ホストが違う)
http://app.example.com ❌ 異なるオリジン(スキームが違う)
https://app.example.com:8080 ❌ 異なるオリジン(ポートが違う)

同一オリジンポリシー(Same-Origin Policy)とは

次にCORSを理解するには 同一オリジンポリシー を知る必要があります。

ブラウザには、セキュリティのために 異なるオリジンからのレスポンスを JavaScript に読み取らせないというルールがあります。これが同一オリジンポリシーです。

https://app.example.com から https://api.example.com へのリクエストは異なるオリジンなので、リクエスト自体はサーバーに届いても、ブラウザがレスポンスを JavaScript に渡しません。
image.png

CORSとは

CORS(Cross-Origin Resource Sharing) は、異なるオリジン間でのリソース共有を安全に行うための仕組みです。

サーバー側が「このオリジンからのアクセスは許可するよ!」とブラウザに伝えることで、クロスオリジンのリクエストを解禁できます。
CORSヘッダーについても後述しますが、ここではCORSを許可するために付与される情報だと考えておけば大丈夫です。

image.png

主要なCORSヘッダー

サーバーが返すCORSヘッダーの種類は以下のとおりです。

ヘッダー名 説明
Access-Control-Allow-Origin 許可するオリジン https://app.example.com または *
Access-Control-Allow-Methods 許可するHTTPメソッド GET, POST, PUT, DELETE
Access-Control-Allow-Headers 許可するリクエストヘッダー Content-Type, Authorization
Access-Control-Allow-Credentials Cookieなどの認証情報を許可するか true
Access-Control-Max-Age プリフライト結果のキャッシュ時間(秒) 3600

プリフライトリクエスト(Preflight Request)とは

次にプリフライトリクエストについてです。

プリフライトリクエストとは、本番のリクエストを送る前に「このリクエストを送っても大丈夫ですか?」とサーバーに事前確認する仕組みです。HTTPのOPTIONSメソッドを使って確認します。

なぜこの仕組みが必要かというと、前述のとおりCORSはレスポンスをブラウザがブロックする仕組みです。しかし、リクエスト自体はサーバーに届くため、DBへの書き込みなど副作用のある操作が実行されてしまってから「見せられない」となっては遅いケースがあります。プリフライトはそれを事前に防ぐためのガードです。

プリフライトが必要な条件

すべてのクロスオリジンリクエストがプリフライトを送るわけではありません。以下の シンプルリクエスト の条件をすべて満たす場合は、プリフライトなしで直接リクエストが送られます。

シンプルリクエストの条件:

  • メソッドが GETPOSTHEAD のいずれか
  • カスタムヘッダーを含まない(Content-Typeapplication/x-www-form-urlencodedmultipart/form-datatext/plain のみ)

条件を満たさない場合(例:Content-Type: application/jsonAuthorization ヘッダーを使う場合)は、プリフライトリクエストが必要 になります。

プリフライトリクエストの流れ

プリフライトリクエストとは、「本番のリクエストを送っても大丈夫ですか?」とサーバーに事前確認する仕組みです。HTTP の OPTIONS メソッド を使います。

image.png

ポイント:

  • ① プリフライトで「これからこんなリクエストを送りたい」と事前確認
  • ② サーバーが許可なら200で返す
  • ③ 許可されたら本番リクエストを送る
  • Access-Control-Max-Age を設定すると、一定時間プリフライトの結果をキャッシュして2回目以降はスキップできる

プリフライトが失敗するケース

プリフライトが失敗すると、本番リクエストはブロックされます。よくある原因は以下のとおりです。

  1. サーバー側でCORSヘッダーが設定されていない
  2. Access-Control-Allow-Origin に該当オリジンが含まれていない
  3. Access-Control-Allow-Methods に使いたいメソッドが含まれていない
  4. Access-Control-Allow-Headers にカスタムヘッダーが含まれていない

ヘッダーの設定はAPI Gatewayで行う場合、コンソール上から行えます。

image.png

さいごに

CORSとプリフライトリクエストについてまとめます:

項目 まとめ
CORS 異なるオリジン間でのリソース共有を許可する仕組み
プリフライト 本番リクエスト前にサーバーへ事前確認するOPTIONSリクエスト
必要な条件 カスタムヘッダーや application/json を使う場合など
AWSでの対応 API Gateway・Lambda・S3・CloudFront それぞれで設定が必要

「CORSエラーが出たらとりあえず Access-Control-Allow-Origin: * にする」はセキュリティ的にNGです。本番環境では必ず特定のオリジンを指定しましょう。

次回は実際の実装例や設定について書いていこうと思います。
この記事が参考になれば幸いです。

参考

13
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
13
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?