何がプリフライトリクエストをトリガーするか?

どのリクエスト特性がブラウザにCORSプリフライトを送信させるかを理解します。シンプルリクエストの定義と不要なプリフライトを避ける方法を学びます。

Preflight

詳細な説明

シンプルリクエストとプリフライトリクエスト

すべてのクロスオリジンリクエストがプリフライトをトリガーするわけではありません。ブラウザは実際のリクエストがシンプルでない場合にのみOPTIONSリクエストを送信します。この区別を理解することで、不要なラウンドトリップを回避するようAPIを最適化できます。

リクエストがシンプルである条件(すべて満たす必要あり)

  1. メソッドGETHEAD、またはPOST
  2. ヘッダーがCORSセーフリストヘッダーのみ:AcceptAccept-LanguageContent-LanguageContent-Type(制限あり)、Range
  3. Content-Type(存在する場合)が以下のいずれか:
    • application/x-www-form-urlencoded
    • multipart/form-data
    • text/plain

プリフライトをトリガーするもの

トリガー
非シンプルメソッド PUTDELETEPATCH
カスタムヘッダー AuthorizationX-Api-KeyX-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に切り替えることで、それらのエンドポイントのプリフライトを排除しました。

試してみる — CORS Header Builder

フルツールを開く