CORS preflight とは?
- 複雑なリクエストを送る前に、OPTIONS で権限があるかどうかを先に確認すること
- ただし実際には、ほとんどのリクエストでこれが必要になる(JSON/XML ボディがある、認証情報を含む、など)
- これがよくない理由は、実際のリクエストにかかる時間が増えること
- OPTIONS リクエストは基本的にキャッシュできないため、CDN も通常は処理せず、リクエストはサーバーまで到達する
- これらの値はクライアント側でキャッシュされ、デフォルトでは 5 秒しか維持されない
- つまり、Web ページが API ポーリングを 10 秒ごとに行うなら、preflight も 10 秒ごとに 1 回発生する
- 多くの場合、ブラウザクライアントの API レイテンシが増加し、ユーザー視点では性能が半分に落ちる
- また、API サーバーに無駄な負荷を与え、コストも増加させる
- 特にサーバーレスならなおさら。Lambda、Netlify Functions、Cloudflare Workers、Google Cloud Functions はいずれも関数呼び出しごとに課金されるため、この preflight もそこに含まれる
preflight 応答をキャッシュする方法
- ブラウザ側でキャッシュして、不要な同一 preflight リクエストを送らないようにする
- CDN レイヤーでキャッシュして、これらのリクエストを実際のバックエンドサーバーが処理しなくても応答できるようにする
ブラウザ向けの CORS キャッシュ
- preflight 応答に次のヘッダーを追加する
Access-Control-Max-Age: 86400
- Firefox は 86400(24 時間)まで可能だが、Chromium ベースのブラウザでは 7200(2 時間)が最大値
CDN 向けの CORS キャッシュ
- CDN またはプロキシでキャッシュするために、次のヘッダーを追加する
Cache-Control: public, max-age=86400
Vary: origin
- 重要なのは、OPTIONS はデフォルトではキャッシュされるようになっていないため、標準ではないということ。ただし、ほとんどの CDN が対応している
設定例
- AWS Lambda で CORS をキャッシュする
- Node.js で CORS をキャッシュする
- Python で CORS をキャッシュする
- Java Spring で CORS をキャッシュする
2件のコメント
ちょうどこの部分を見ていたところだったので、興味深く拝見しました。
パフォーマンスが真反対に -> パフォーマンスが半分に