Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unable to load cross-origin image (from CloudFront) in Safari

I get the following error when trying to load an image from a CloudFront URL in Safari 8:
Cross-origin image load denied by Cross-Origin Resource Sharing policy.

This only happens on Safari 8. In FireFox 38 and Chrome 41 latest it loads just fine. (Mac 10.10)

My setup:

1. S3 bucket with the following CORS configuration

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

2. A linked CloudFront distribution

The following headers have been whitelisted (under behaviours):

  • Access-Control-Request-Headers
  • Access-Control-Request-Method
  • Origin

3. JavaScript

var img = new Image();
img.crossOrigin = '';
img.onload = function() {
  console.log('image loaded');
}

What I've tried:

1. Checking returned headers from curl

The image is returning the correct headers (notably Access-Control-Allow-Origin)

> curl -sI -H 'Origin: localhost' -H 'Access-Control-Request-Method: GET' http://foo.cloudfront.com/image.jpg
...
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET
Access-Control-Max-Age: 3000
Server: AmazonS3
Vary: Origin,Access-Control-Request-Headers,Access-Control-Request-Method
X-Cache: Hit from cloudfront

2. Checking returned headers in the browser

Interestingly enough the image is NOT returning the Access-Control-Allow-Origin: * header in all three browsers. Why would this be the case?

3. Adding a query string to the URL

Adding a query string (e.g. ?foo) to the URL being loaded WILL cause the Access-Control-Allow-Origin header to be returned in the browser, and allows the image to be loaded in Safari! This is great, but why would adding the query string allow this to work (and also return the Access-Control-Allow-Origin header)?

4. Loading an image from an S3 bucket (not tied to a CloudFront distribution)

Loading an image from another bucket not tied to CloudFront (with an identical CORS config) also works just fine in Safari.

Which initially led me to believe this was specifically a CloudFront issue, but the above point with the query string makes me think otherwise.

This is driving me completely batty. Can anyone help shed some light on the above?


Update

Thanks for the replies. Frustratingly enough, I can't seem to replicate this issue.

Below is a snippet which loads two images (one from an S3 bucket, another from its respective Cloudfront distribution) and they both also appear to load in just fine with the headers you'd expect, contrary to what I said above in point #2.

Unfortunately I'm not really closer to a definite answer, but for now I'm just going to chalk it down to an error on my behalf, potentially requesting an image before my CORS setup as Derek suggested.

var img, imgCloudfront;

img = new Image();
img.crossOrigin = '';
img.onload = function() {
  $('body').append('image loaded<br>');
}
img.src = 'http://sandbox-robinpyon.s3.amazonaws.com/test.jpg';

imgCloudfront = new Image();
imgCloudfront.crossOrigin = '';
imgCloudfront.onload = function() {
 $('body').append('image (cloudfront) loaded<br>');
}
imgCloudfront.src = 'http://d32d4njimxij7s.cloudfront.net/test.jpg';
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
like image 975
Robin Pyon Avatar asked Apr 02 '15 17:04

Robin Pyon


People also ask

How do I enable CORS in CloudFront?

For enabling CORS we need to configure Cloudfront to allow forwarding of required headers. We can configure the behavior of Cloudfront by clicking on Cloudfront Distribution's "Distribution Settings". Then from the "Behaviour" tab click on "Edit". Here we need to whitelist the headers that need to be forwarded.

How do I get Origin Access Identity in CloudFront?

To create an origin access controlSign in to the AWS Management Console and open the CloudFront console at https://console.aws.amazon.com/cloudfront/v3/home . In the navigation pane, choose Origin access. Choose Create control setting.


1 Answers

Double checkout your cloudfront behavior settings. Did you add the custom header Origin. It should be Access-Control-Allow-Origin. I recently setup cloudfront as well and found this article helpful: http://kennethjiang.blogspot.com/2014/07/set-up-cors-in-cloudfront-for-custom.html

I've had problems with clearing the cache on cloudfront. If you had requested an image before your CORS setup, cloudfront may just return what it had before so your new configurations are not reflected. You can try to run an invalidation, it's one of the cloudfront behavior tabs. I got inconsistent results with this. If you want to make sure it's working, upload a new image and test with that. I'm using rails and on occasion I bump up an asset versions which causes all my asset sto have a new fingerprint and that solves the caching issues because each file has a new name.)

Regarding your question about the query string. You probably got a cache miss from cloudfront. You can try to repeat the exercise with curl to see the response X-Cache: Hit from cloudfront is present or not. In the cloudfront behavior settings there is a config for 'Forward Query Strings'. That may play a factor.

In my setup, I had an intermediate varnish cache so I had to mess with that too to make sure all the headers made it through. Doesn't seem like you have that but it's something to watch out for.

like image 89
Derek Avatar answered Oct 12 '22 14:10

Derek