13

I have a Rails app, hosted on Heroku. During deployment assets are synced with an Amazon S3 bucket via the asset_sync gem and views call those assets through CloudFront. However, fonts are not rendered when viewing the website with Firefox (files are loaded in the Net tab of Firebug, but simply not used). Safari works great.

I have the following CORS config on S3:

<?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>Content-*</AllowedHeader>
    <AllowedHeader>Host</AllowedHeader>
</CORSRule>
</CORSConfiguration>

My app also sets the following headers:

Access-Control-Allow-Origin: *
Access-Control-Request-Method: *

But CloudFront returns fonts without them... Why aren`t fonts loaded? Thanks in advance.

Soyak
  • 267
  • 2
  • 3
  • 11
Dimitar Vouldjeff
  • 2,067
  • 3
  • 19
  • 24

4 Answers4

8

Some versions of Internet Explorer and Firefox consider fonts an attack vector and will refuse loading them if they are being provided by another domain (cross domain policy).

On standard HTTP servers all you need to do is add the Access-Control-Allow-Origin: * header to bypass the CORS policy. The problem is S3 doesn’t support sending it. (Though according to the specification it should support CORS, the header is not sent).

There is a workaround. CloudFront can be pointed at another server that can send the Access-Control-Allow-Origin header (You can do that with the server that serves your app ;) ).

This can be done by adding a Custom Origin to your CloudFront distribution from the AWS Console. Next you will have to add Behaviours with your font types and the newly added Origin. You can use wildcards for the filename. (You’ll need to do this once for each font type that you have).

Example:

Path Pattern: /assets/*.woff

When ready you can validate the header existence with:

curl -I http://cloudfrontid.cloudfront.new/assets/font.woff

Hopefully you will see the Access-Control-Allow-Origin header, provided by your server along with the file itself, cached by CloudFront with the header included.

Hope it helps!

Itay Grudev
  • 7,055
  • 4
  • 54
  • 86
  • 1
    I haven't tried it, but I think this will work. The problem is that Custom Origins in Cloudfront are $600/month if you want to use them with https :( – Jeremy Raines Nov 19 '13 at 18:33
2

Try invalidating your (cached) font files in Cloudfront: http://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/Invalidation.html#invalidating-objects-console

I had a similar issue today. I read an article that suggested CORS configurations are cached in CloudFront. I resolved my issue by invalidating my font files.

smockle
  • 2,162
  • 17
  • 19
0

This is what my CORS config looks like. I have a different AllowedHeader than you. I don't use asset_sync.

<?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>Authorization</AllowedHeader>
    </CORSRule>
</CORSConfiguration>
nobody
  • 19,814
  • 17
  • 56
  • 77
  • are you using cloudfront? – Jeremy Raines Nov 14 '13 at 19:11
  • Oops, sorry. The CSS file at http://assets-p.artcat.com/file_uploads/file_asset/asset/a9424d79e56d858ff2d7a04012af74980a17e855/cb7523d37b941ca5f81467c723f48e18.css is loaded from Cloudfront, but it appears the fonts are loaded from S3. I think we had trouble making it work via cloudfront. – Barry Hoggard Nov 15 '13 at 01:27
  • 1
    This is the CORS file on the S3 bucket serving the fonts https://gist.github.com/bhoggard/7477688 – Barry Hoggard Nov 15 '13 at 01:32
0

On June 26, 2014 AWS added support for CORS in CloudFront, so now you can make this work with just CloudFront and S3.

This SO answer provides info about enabling CORS support for a particular CloudFront distribution: https://stackoverflow.com/a/24459590/3195497

In addition you will need to enable CORS on your S3 bucket. One of the answers here says in regard to S3:

Though according to the specification it should support CORS, the header is not sent

From my testing this is only partially true. If the Origin header is sent in the request then S3 will correctly send the Access-Control-Allow-Origin header. If the Origin header is not sent then S3 will not send the Access-Control-Allow-Origin header.

In the past this has caused problems with CloudFront. If you made any requests to CloudFront without an Origin request header then CloudFront will cache a response without the Access-Control-Allow-Origin response header. This might happen because you are testing the asset with a curl command and you don't include the Origin request header. Now when you make a request to CloudFront with the Origin header, CloudFront would ignore the Origin header and serve the cached response without the Access-Control-Allow-Origin header.

With the changes recently released to CloudFront, you can configure your distribution to take the Origin request header into account. In this case CloudFront will cache different responses, one response for each value of the Origin header.

Community
  • 1
  • 1
scytacki
  • 1
  • 1