アクトインディ開発者ブログ

子供とお出かけ情報「いこーよ」を運営する、アクトインディ株式会社の開発者ブログです

Safariで「Preflight response is not successful」と言われたので対処した

morishitaです。

CloudFront + S3 で配信しているJSONファイルを別ドメインのJavaScriptで取らせようとしたら Preflight response is not successful というエラーが出てリクエストが失敗するという事象があったので対処しました。

発生したのは PC、iOS、iPadOS の Safariのみです。

結論を言ってしまうと、CloudFrontBehavierAllowed HTTP MethodsOPTIONS を追加することで解決しました。

アプリケーションの構成

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 では BehaviorAllowed HTTP MethodsGETPOST のみを指定していたため、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


  1. 説明が長くなるので端折っています。詳しくはSimple Requestを参照してください。