2018.09.06
S3に配置したCSSファイルやJavaScriptファイルをCloudFront経由で利用しようとするとブロックされる。 FontAwesomeのファイルをCloudFront経由で読み込むようなWebアプリケーションを作ったら、アイコンが全部豆腐になってしまった。
CORSとは、「Cross-Origin Resource Sharing」の頭文字を取ったもの。 オリジン(Origin)とは、
http://
やhttps
など)example.com
など):3000
など)のこと。
これらは全て別オリジンということになる。
オリジンをまたいでAjax通信をすることは基本的に禁止されているが、それを許可するための仕組みがCORSである。
Ajaxリクエストを発行する側をサーバーA、Ajaxリクエストを受けてレスポンスを返すサーバーをBとしたとき、サーバーBのHTTPヘッダーに
Origin: http://example.com
のようにアクセスを許可したいオリジンを指定することでCORSの設定ができる。
この場合、サーバーBのコンテンツをAjax通信で取得できるオリジンはhttp://example.com
となる。
どのオリジンからでも参照できるようにするには、*
を指定すればよい。
AWS S3はマネージドサービスのため、ApacheやNginxのように設定ファイルを直接自分で編集することはできない。AWSマネジメントコンソールか、AWS CLIから操作をする必要がある。
HTTPとHTTPSで利用できるサイトの場合は、以下のように<CORSRule>
ブロックを2つ書く。
HTTPのみ、もしくはHTTPSのみの場合は不要な方の<CORSRule>
ブロックを削除すればOK。
<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
<CORSRule>
<AllowedOrigin>https://example.com</AllowedOrigin>
<AllowedMethod>GET</AllowedMethod>
<MaxAgeSeconds>3000</MaxAgeSeconds>
<AllowedHeader>*</AllowedHeader>
</CORSRule>
<CORSRule>
<AllowedOrigin>http://example.com</AllowedOrigin>
<AllowedMethod>GET</AllowedMethod>
<MaxAgeSeconds>3000</MaxAgeSeconds>
<AllowedHeader>*</AllowedHeader>
</CORSRule>
</CORSConfiguration>
ちなみに2006-03-01
という日付が見えるが、これは変更してはいけない。
AWS内でCORSの設定を管理するXMLのフォーマットにバージョンがあり、それを指定しているものなので変更すると動かなくなる。
S3に置いたコンテンツをCloudFrontでキャッシュして配信する構成の場合、HTTPヘッダーもキャッシュする設定にしないとせっかく組んだCORSの設定が反映されない。
CloudFrontの設定画面から以下のように設定する。
CloudFrontは設定を変更しても今キャッシュされているファイルが再度オリジンから取得されるわけではない。 そこで、コンテンツをオリジンから再取得するために以下のどちらかの操作をする必要がある。
オリジンのコンテンツのファイル名を変更して、CloudFront越しにアクセス
CloudFrontのInvalidation(キャッシュ削除)を申請する
サーバーサイドのフレームワークにはRuby on Railsを使っていて、Asset Pipelineを利用してCSSやJavaScriptをビルドしているので、1つ目の方法を基本的に使っている。
ただ、一度プリコンパイルしたCSS・JavaScriptファイルは変更しないとダイジェストが変わらないので、何かしらの変更をして、その後プリコンパイルを実行して、S3にアップロードするという流れになる。
AWS CLIを使ってCORSの設定を変更できる。 詳しい手順は以下の記事にまとめた。