何がプリフライトリクエストをトリガーするか?
どのリクエスト特性がブラウザにCORSプリフライトを送信させるかを理解します。シンプルリクエストの定義と不要なプリフライトを避ける方法を学びます。
Preflight
詳細な説明
シンプルリクエストとプリフライトリクエスト
すべてのクロスオリジンリクエストがプリフライトをトリガーするわけではありません。ブラウザは実際のリクエストがシンプルでない場合にのみOPTIONSリクエストを送信します。この区別を理解することで、不要なラウンドトリップを回避するようAPIを最適化できます。
リクエストがシンプルである条件(すべて満たす必要あり)
- メソッドが
GET、HEAD、またはPOST。 - ヘッダーがCORSセーフリストヘッダーのみ:
Accept、Accept-Language、Content-Language、Content-Type(制限あり)、Range。 - Content-Type(存在する場合)が以下のいずれか:
application/x-www-form-urlencodedmultipart/form-datatext/plain
プリフライトをトリガーするもの
| トリガー | 例 |
|---|---|
| 非シンプルメソッド | PUT、DELETE、PATCH |
| カスタムヘッダー | Authorization、X-Api-Key、X-Requested-With |
| JSON Content-Type | Content-Type: application/json |
| ReadableStreamボディ | ストリーミングリクエストボディ |
なぜapplication/jsonがプリフライトをトリガーするか
最も一般的な驚き:Content-Type: application/jsonの送信 — モダンなREST APIでは標準的 — は、3つのセーフリストコンテンツタイプのいずれでもないため、自動的にプリフライトをトリガーします。
不要なプリフライトの回避
- 読み取り専用エンドポイントでは、JSONボディのPOSTの代わりにクエリパラメータ付きの
GETを使用します。 - クライアントとサーバーの両方を制御する場合、プリフライトをキャッシュするために十分な
Access-Control-Max-Ageを設定します。 - 必要でない限りカスタムヘッダーの追加を避けてください — 各固有のヘッダーの組み合わせが新しいキャッシュキーを作成します。
DevToolsでの確認
ネットワークタブを開き、「すべて」フィルタを有効にして、リクエストのペアを探します:OPTIONSの後に実際のメソッドが続きます。予期しないOPTIONSリクエストが表示された場合、リクエストがどのトリガー条件に一致するかを確認してください。
ユースケース
フロントエンド開発者がAPIコールが遅いことに気づき、すべてのfetchリクエストがダブルラウンドトリップを生成していることを発見しました。読み取り専用コールをJSONのPOSTからクエリパラメータ付きGETに切り替えることで、それらのエンドポイントのプリフライトを排除しました。