デザインワン・ジャパン Tech Blog

DesignOne Japan | Activate the World.

静的ファイル配信システムをCloudFront+S3の構成に移行したときCORSエラーにハマったお話

まえがき

最近、運動不足で地球の重力を日増しに感じている インフラエンジニアの 冨田(@komitta)です。 今回は移行作業時のちょっとした失敗談をお話ししたいと思います。

移行内容について

エキテンでは静的ファイルを配信するドメインとユーザーが閲覧する公開用のドメインを分けて構築しています。

静的ファイルを配信する環境の元々の構成はEC2サーバーを使用して公開しておりましたが、 より可用性およびコストパフォーマンスの優れているCloudFront+S3の構成に切り替え対応を行いました。

f:id:doj_tomi:20220228070917p:plain
構成図

移行が終わりページも表示されてめでたしめでたし

...とはならなかったお話です。

フォントファイルでCORSエラーが出力されてる

移行対応後に、表示がおかしいとタレコミがあり見てみると、とあるページにてフォントファイルのみCORSエラーとなっている状態を発見しました。

f:id:doj_tomi:20220222153847p:plain
CORSエラー画面

そこでCORSについて改めて調べてみることに。

そもそもCORSとは

CORSはCross-Origin Resource Sharingの略で別ドメインへの非同期リクエスト(XMLHttpRequest等)についてデフォルトではアクセスできないようブロックする仕組みです。*1

f:id:doj_tomi:20220228062729p:plain
CORSの説明画像

developer.mozilla.org

たしかにエキテンサイトは公開ページに含まれる静的ファイルとドメインが異なっているので意識する必要はありそう。 ただし XMLHttpRequestのアクセスでもないし、そもそも許可できていなかったらページ全体が見れないはず。。

なぜフォントファイルだけ...

というわけでもう少し詳しく確認してみました。

CORSが必要な条件を確認してみた

MozillaのサイトにCORSが使うリクエストの記述が記載されてました。

What requests use CORS?

This cross-origin sharing standard can enable cross-origin HTTP requests for:

  • Invocations of the XMLHttpRequest or Fetch APIs, as discussed above.

  • Web Fonts (for cross-domain font usage in @font-face within CSS) , so that servers can deploy TrueType fonts that can only be loaded cross-origin and used by web sites that are permitted to do so.

  • WebGL textures.

  • Images/video frames drawn to a canvas using drawImage().

  • CSS Shapes from images.

This is a general article about Cross-Origin Resource Sharing and includes a discussion of the necessary HTTP headers.

developer.mozilla.org

CSS内部から呼び出されるフォント(Web Fonts (for cross-domain font usage in @font-face within CSS) )の記述を確認。

今回はこれに該当していました。

つまりCSS内部から呼び出される別ドメインへのフォントファイルに関してはレスポンスヘッダーの中に Access-Control-Allow-Origin の値を返す必要がありました。

S3側でバケットポリシー対応が必要だった

CloudFrontのバックエンドにいるのはS3なのでAWSのマニュアルを確認したところ、マニュアルにCORSの設定方法がしっかり書かれていました\(^o^)/

docs.aws.amazon.com

S3 バケット > アクセス許可 > CORS設定

[
    {
        "AllowedHeaders": [
            "*"
        ],
        "AllowedMethods": [
            "GET",
            "HEAD"
        ],
        "AllowedOrigins": [
            "mydomain.com"
        ],
        "ExposeHeaders": [],
        "MaxAgeSeconds": 3000
    }
]

上記の設定後、エラーがでなくなることを確認し今度こそ完!!

f:id:doj_tomi:20220228060925p:plain
CORSリクエスト成功画面

まとめ

CORS周りの理解がふんわりしていたために、発生した問題でした。

仕様の理解は大事ですね。(英語力も大事)

あと思ったよりこの問題の情報が少なくて、原因究明にたどり着くのに時間がかかりました。

おわりに

仲間を募集しております

募集中の職種については以下を御覧ください。

www.wantedly.com