13

Upon trying to load an image (with crossorigin set to anonymous) from an Amazon S3 server, we are still getting the dreaded error:

 XMLHttpRequest cannot load 
 http://resource-url No 
'Access-Control-Allow-Origin' header is present on the requested resource. Origin
'http://server-url' is therefore not allowed access.

We have tried several CORS configurations, such as

<?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>

as well as Amazon's default CORS configurations. Still, same error.

A couple of other notes:

  • This issue is present in Chrome but not Firefox.
  • The images are being loaded as an AFrame asset (hence the XMLHttpRequest)
  • curl -XGET -H 'Origin: anonymous' http://resource-url returns what appears to be the image, starting with ?PNG
  • For Chrome, here are the headers. Here is the response.
  • For Firefox, here are the headers. The response is the image.
  • Here are the AFrame docs on CORS. However, since the images are fetched from S3 and serving them on Github Pages is not really an option, it might not be useful.

I'm at my wit's end, so any help at all would be greatly appreciated. Thank you so much!

hyperdo
  • 389
  • 5
  • 11
  • 1
    `Upon trying to load an image (with crossorigin set to anonymous)` - can you show this code, the error message suggests you are using `XMLHttpRequest` not "loading an image" – Jaromanda X Dec 28 '16 at 23:05
  • 3
    Can you check that the request headers includes an `Origin` header - I've read that without an Origin header, Amazon S3 server wont respond with any CORS headers [ref](http://docs.aws.amazon.com/AmazonS3/latest/dev/cors.html#cors-eval-criteria) – Jaromanda X Dec 28 '16 at 23:10
  • are you sure it isn't a browser security issue that you'd need to take on with something like discussed here ? http://stackoverflow.com/questions/30939979/get-around-no-access-control-allow-origin-header-is-present-on-the-requested – Tom22 Dec 28 '16 at 23:12
  • Hmm, that's true. The context for this is that AFrame (a webvr library) is loading this image as an asset. I guess it uses XMLHttpRequest by default. Still, I think the main culprit is that S3 is not actually sending a CORS header? – hyperdo Dec 28 '16 at 23:16
  • @Tom22 what solution would you suggest in production that doesn't use Ember.js/ – hyperdo Dec 28 '16 at 23:18
  • @JaromandaX Thanks! Is there a way to tell if your XMLHttpRequest is sending a CORS header? – hyperdo Dec 28 '16 at 23:19
  • 1
    `XMLHttpRequest is sending a CORS header` - not sure what you mean by this, I never said that XMLHttpRequest needs to send CORS headers ... CORS headers are RECEIVED by the client, not SENT – Jaromanda X Dec 28 '16 at 23:21
  • @JaromandaX sorry, I meant a CORS header being included in the request. I'm adding some additional info in the question -- thanks for your help thus far. – hyperdo Dec 28 '16 at 23:22
  • 1
    `I meant a CORS header being included in the request` again, CORS headers are in the **response** ... use the browser developer tools network tab ... check the request/response headers for the failing request ... specifically (all I could find in the documentation) check that the **request** headers includes an `Origin` header - without this, Amazon S3 wont respond with CORS **response** headers (as i mentioned before) – Jaromanda X Dec 28 '16 at 23:25
  • @JaromandaX thanks for the clarification. I'll check the headers and report back. In the meantime, if you could take a look at the notes I've added to the original question, I'd really appreciate that. Thanks so much. – hyperdo Dec 28 '16 at 23:28
  • 1
    `This issue is present in Chrome but not Firefox` - ignore everything I said. The fact that it works in any browser means that the server side is correct, and the client side is at least correct in Firefox ... I'm surprised there's a difference in Chrome vs Firefox ... the page getting the resource, is it `http://` as well? (not `https://` for example) – Jaromanda X Dec 28 '16 at 23:34
  • @JaromandaX I've added the response and header images to the question. If there's anything else you'd like me to do, please let me know. – hyperdo Dec 28 '16 at 23:42
  • 1
    Interesting: See how in firefox, the response headers have no CORS headers whatsoever? – Jaromanda X Dec 28 '16 at 23:48
  • Good point. I've managed to solve the problem by creating a CORS proxy, like the one seen [here](https://blog.javascripting.com/2015/01/17/dont-hassle-with-cors/). Thanks for all your help, @JaromandaX . – hyperdo Dec 29 '16 at 00:03
  • Firefox -- you appear to have already had this file in your browser cache -- hence `304 Not Modified` -- and that was likely the root of the problem. S3 should not require a proxy for CORS to work correctly. – Michael - sqlbot Dec 29 '16 at 04:29
  • Correct @Michael-sqlbot, this does work in Firefox. But, chrome is still blocking it. You have to allow it manually in chrome but using some plugin or, so to make it work But, this may not be a good idea for production eh ? – Sudip Jun 09 '17 at 06:00

2 Answers2

8

Possibly add <AllowedMethod>HEAD</AllowedMethod>:

<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
    <CORSRule>
        <AllowedOrigin>*</AllowedOrigin>
        <AllowedMethod>GET</AllowedMethod>
        <AllowedMethod>HEAD</AllowedMethod>
        <MaxAgeSeconds>3000</MaxAgeSeconds>
        <AllowedHeader>*</AllowedHeader>
    </CORSRule>
</CORSConfiguration>

It seems that there are pre-flight checks (for server load checks) that some modern browsers send using the HEAD method. More reading here and here.

David Lemayian
  • 2,242
  • 18
  • 17
  • 1
    THANK YOU. I was searching everywhere with references to the symptom and what you've stated here is the root cause. – bfeist Oct 20 '20 at 01:41
  • :) Glad this helped and all the best @bfeist – David Lemayian Oct 21 '20 at 05:16
  • I don't know if this fixed it or just the side effect of invalidating CloudFront. I was looking in the Network Trace and it was a GET request and not getting the headers, but it's working now so i upvoted :) – Ken Waln Dec 15 '20 at 00:22
  • On second thought, maybe CloudFront was sending a HEAD request before serving the cached copy? I only know for sure the browser was failing on the GET. – Ken Waln Dec 15 '20 at 00:24
2
<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
<CORSRule>
<AllowedOrigin>*</AllowedOrigin>
<AllowedMethod>HEAD</AllowedMethod>
<AllowedMethod>GET</AllowedMethod>
<AllowedMethod>PUT</AllowedMethod>
<AllowedMethod>POST</AllowedMethod>
<AllowedMethod>DELETE</AllowedMethod>
<AllowedHeader>*</AllowedHeader>
</CORSRule>
</CORSConfiguration>

After adding the above xml code, you need to invalidate the cache.

jarora
  • 4,400
  • 2
  • 30
  • 39
Sunil
  • 29
  • 1