morishitaです。
CloudFront + S3 で配信しているJSONファイルを別ドメインのJavaScriptで取らせようとしたら Preflight response is not successful というエラーが出てリクエストが失敗するという事象があったので対処しました。
発生したのは PC、iOS、iPadOS の Safariのみです。
結論を言ってしまうと、CloudFront の Behavier の Allowed HTTP Methods に OPTIONS を追加することで解決しました。
アプリケーションの構成
Nuxt.js の SPAで、AWS Amplify Console で配信しています。 このアプリケーションでは、別途用意したCloudfornt + S3 からJSONファイルを取得します。 そのJSONファイルの取得で Preflight response is not successful が発生しました。
Preflight Requestって?
Preflight Request は CORSのリクエストを送信する際にブラウザが Simple Requestでないと判断したら送信するリクエストです。実際のリクエストを送信しても安全かどうかを確かめる目的で送信されます。
次の条件をすべて満たす場合、Simple RequestとみなされてPreflight Requestを送信しません。
- リクエストは GET, POST, HEAD メソッドのいずれか
- 次のリクエストヘッダ以外をセットしていない1
- Accept
- Accept-Language
- Content-Language
- Content-Type
- Content-Type が次のいずれか
- application/x-www-form-urlencoded
- multipart/form-data
- text/plain
逆にいうと、上記条件を満たさない場合には、Preflight Requestが送られるということです。実際に送るかどうかはブラウザの実装状況次第のようですが。
Preflight Request は OPTIONS メソッドのリクエストです。
私が用意した CloudFormation では Behavior の Allowed HTTP Methods で GET と POST のみを指定していたため、Preflight Request に失敗していたようです。
改めて、CloudFront + S3 の CORS 設定について整理する
どんなドメインからもXHRやFetchでGETできる最低限の設定について改めて整理します。
S3の設定
次のようにバケットの「アクセス権限」-「CORSの設定」を開いて CORS 構成エディターで次の様に設定します。
<?xml version="1.0" encoding="UTF-8"?> <CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/"> <CORSRule> <AllowedOrigin>*</AllowedOrigin> <AllowedMethod>GET</AllowedMethod> <MaxAgeSeconds>3000</MaxAgeSeconds> <AllowedHeader>*</AllowedHeader> </CORSRule> </CORSConfiguration>
CloudFrontの設定
CloudFrontの設定の肝はBehavierの次の様に設定することです。
設定項目 | 設定値 |
---|---|
Allowed HTTP Methods | ※ OPTIONSを含むものを選択する 例) GET, HEAD, OPTIONS |
Cache Based on Selected Request Headers | Whitelist を選択 |
Whitelist Headers | Origin を含める |
他の設定項目はアプリケーションの要件にしたがって任意に設定してください。
最後に
アクトインディではエンジニアを募集しています。 actindi.net
-
説明が長くなるので端折っています。詳しくはSimple Requestを参照してください。↩