Access-Control-Allow-Originヘッダ関連のエラーがCORSなリクエスト時に出る場合の対処【Apache】

 

Add-Header-for-CORS-Request_1_sh

ブラウザのアドレスバーに表示されているドメインとは別のドメインへWebフォントを取得しに行くと、同一生成元ポリシー(クロスドメイン制約)に引っかかって、ブラウザ側が「Access-Control-Allow-Origin ヘッダが無い」というエラーを吐き、Webフォントが表示されない。という事例に遭遇したので、サーバー側での対処法と Origin ドメインを複数許可する設定方法をメモしておきます。

ちなみにこのエラーは Web フォントだけでなく、Ajax で Cross-Origin Resource Sharing(CORS)なリクエストを投げる場合にも出るエラーと思います。

Chrome のコンソールに吐かれたエラー内容はこんな感じ。

Font from origin ‘http://example.com’ has been blocked from loading by Cross-Origin Resource Sharing Policy: No ‘Access-Control-Allow-Origin’ header is present on the requested resource. Origin ‘http://example.jp’ is therefore not allowed access.

CORS 絡みはあまり調べた事はなかったのですが、まさかWebフォントでも引っかかるとは思わず、面食らいました。

という事で、Apache の .htaccess の設定にこんな感じの設定を入れて回避。

SetEnvIf Origin "^http://(i|s|www)\.example.com$" ACAO=$0
Header set Access-Control-Allow-Origin %{ACAO}e env=ACAO

実際には、FilesMatch とかで特定ファイル名・拡張子だけに適用するとか、mod_headers.c のモジュールチェックとかの記述も要るかも。

W3C勧告を素直に解釈するなら、Access-Control-Allow-Origin ヘッダにはスペース区切りで複数ドメインを列挙できることになってはいるのですが、以下の注意書きでも触れられているとおり、実際のブラウザ実装では Access-Control-Allow-Origin ヘッダに複数ドメインが書かれていると、エラー扱いにされるケースはあります。

具体的には、Chrome で CORS なリクエスト時、複数 Origin ドメインを許可するレスポンスを受け取ると以下のようなエラーが吐かれます。

The ‘Access-Control-Allow-Origin’ header contains multiple values.

このあたりの事情や、開発時の事情も考慮すると、個別のドメイン毎に Access-Control-Allow-Origin ヘッダ に1ドメインのみ返す設定を Web サーバ側に入れたほうが楽であろう。ということで、今回は先の書き方にしてみました。

ちなみにスイスメイドのアーミーナイフ、こと mod_Rewrite でも似たような設定は可能です。拝借してきた記述ですが、ここに転載させていただきます。

RewriteCond %{HTTP:Origin} \.example\.com$
RewriteRule . - [E=CORS_OK:1]
Header set Access-Control-Allow-Origin "*" env=CORS_OK

CDN配信時はどうする?

うちでは SoftLayer の Origin-Pull な CDN サービスを使っているのですが、少なくとも、SoftLayer のダッシュボードには Access-Control-Allow-Origin ヘッダに関する設定項目は見当たりませんでした。

ただ、SoftLayer はチケット経由で問い合わせればダッシュボードに無い機能でも使える場合があるので(有償の場合もあると思いますが)、必要があって乗り気になれば、一度、確認してみたいとは思っています。今はサポートも日本語対応していますしね。

とは言え、この項目は出来ればセルフサービスで触りたい内容ではあるので、不満っちゃ不満ですが。

ってことで、ちょっと調べてみたら、AWS の CloudFront だとこのあたりの設定ができるのですね。

Origin ヘッダ毎にキャッシュしてくれるあたりとか、分かってる感が素晴らしいじゃないですか。

関連情報:

Hatena Pocket Line

コメントを記入