iframeを使ってたら今まで問題なかったリクエストがCORSエラーで怒られるようになった

2019年12月17日
投稿者:若林 奨太
カテゴリ:開発全般 タグ:

こんにちは。鈴木商店の若林 (@itigoore01) です。

タイトルどおりですが、iframeを使ったら急にCORSで怒られることになる罠にハマったので、同じ状況に困った方に役立てて頂きたく原因と解決策をここに残します。
かなり状況が限定されているので、同じ状況になる人が出てきて、かつこのページを見つけてもらえる可能性はかなり低そうですが……。

同じく状況は限られますが他にもCORSについての記事を書いているので、この記事の状況とは違う場合は以下の記事もご参照ください。
【Angular】「[Error] Blocked 〜 cross-origin request.」のようなエラーが出たときの対処方法

状況

ではまず、エラーとしては以下のようなものです。

状況としては以下のような感じです。

  • ChromeとSafariで確認(他ブラウザは確認していないだけなので、同様の状況が発生する可能性あり)
  • iframeタグを記述している親ページ(以下 親ページ )と、iframesrcで指定されているページ(以下 iframeページ)は別オリジン
  • また画像を取得しにいくサーバーと、親ページ、iframeページも別オリジン
  • もちろん親ページもiframeページも両方ともサーバー側のAllow-Origin設定は済ませている
  • 親ページとiframeページで同じ画像データをAjaxで取得しており、これがCORSエラーで怒られる
    • キャッシュを削除した状態で、最初に画像取得のリクエストを投げたページだけはCORSエラーが発生せずにちゃんと取得できる
    • しかし、あとに取得することになったページはCORSエラーが発生してしまう

↑こんな感じです。
キャッシュのくだりで察しのいい方はわかるかも知れませんが、原因を一言でいうとキャッシュです。
では、原因から見てみましょう。

原因

話を単純にするために、はじめにリクエストを投げたページは親ページ、その後リクエストを投げてCORSエラーが発生するページをiframeページとします。
また、親ページはhttps://xxxxxx.xxx iframeページはhttps://zzzzzz.zzz とします。

処理としては、まず親ページは画像Aを取得するためにリクエストを投げます。

クロスオリジンリクエストなのでpreflightリクエストのあとGETとなりますが、そのときのレスポンスは以下のように Access-Control-Allow-Origin がヘッダーに設定されます。

ここで、ブラウザちゃんはえらいのでレスポンスをキャッシュしてくれます。

次にiframeページで同じく画像Aを取得するためのリクエストを投げます。
するとブラウザちゃんは、良かれと思ってキャッシュしていたレスポンスを返してくれます、ヘッダーもそのまま。

iframeページは https://zzzzzz.zzz、しかしヘッダーの Access-Control-Allow-Originhttps://xxxxxx.xxx
Access-Control-Allow-Originにはhttps://zzzzzz.zzzは設定されていないため、CORSエラーが発生しているよ!とブラウザちゃんは怒る。

これが原因です。

解決策

結局キャッシュが原因なので、いわゆるCache Bustingが使えます。

例えば親ページのほうだけ https://aaaaaa.aaa/image.jpg?v=${ランダムななにか} のように Cache Bustingするためのクエリ文字列を付与してあげれば、親ページとiframeページで同じURLの画像を見に行くことがなくなるので、しっかり取得できるようになります。


コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です