38

I'm storing JSON objects in Amazon S3, and I'd like to load that data directly from S3 from Javascript. My GET looks pretty generic:

$.ajax({
    'type':'GET',
    'url':'http://s3.amazonaws.com/mybucketname/'+id,
    'dataType':'text',
    'success':function(msg) {
        alert(msg);
    }
});

I get the following error:

XMLHttpRequest cannot load http://s3.amazonaws.com/whatever/whatever. Origin http://mylocalhostname:9000 is not allowed by Access-Control-Allow-Origin.

I can get that URL from S3 using curl, or by navigating there directly from my browser. Am I really going to have to proxy all of these requests through my own servers?

Ben Dilts
  • 10,535
  • 16
  • 54
  • 85
  • possible duplicate of [Amazon S3 and Cross-Origin Resource Sharing (CORS)](http://stackoverflow.com/questions/4717006/amazon-s3-and-cross-origin-resource-sharing-cors) – epascarello Jul 03 '12 at 17:23
  • Or another dupe: http://stackoverflow.com/questions/8674776/pull-data-our-of-json-with-jquery Shows JSONP solution. – epascarello Jul 03 '12 at 17:40

11 Answers11

43

S3 doesn't send the 'Access-Control-Allow-Origin' header if you use the wildcard * like:

<AllowedOrigin>*</AllowedOrigin>

To force s3 sending the AllowedOrigin header but still let your content be loaded from any site, use this:

<AllowedOrigin>http://*</AllowedOrigin>
<AllowedOrigin>https://*</AllowedOrigin>
Ludo - Off the record
  • 5,153
  • 4
  • 31
  • 23
  • 4
    Searched all over, this was the solution for me. Not in Amazon's docs but worked immediately. You can list all three in the same CORS rule – grokpot Dec 02 '14 at 22:28
  • 1
    Likewise, of all the attempted fixes I made, this was the silver bullet. – Christian Dec 10 '14 at 02:36
  • 1
    This did it for me as well. I was at my wits end. Spent two hours trying everything I could think of and nothing was working. You would think they would either mention this in the docs or if not that, then make a change so either way works as expected. – Blimey85 May 27 '15 at 04:25
  • 1
    Worked for me also! I was trying to load an HTML file from S3 to Heroku using the jquery load function. – Adrien Renaud Sep 02 '16 at 01:29
  • Very similar as for @AdrienRenaud, solved my issue with an HTML file using native XMLHTTPRequest() class. – The Onin Dec 05 '17 at 22:10
40

S3 now supports Cross Domain Requests using CORS file.

You can find more information here:

http://docs.amazonwebservices.com/AmazonS3/latest/dev/cors.html#how-do-i-enable-cors

and:

http://aws.typepad.com/aws/2012/08/amazon-s3-cross-origin-resource-sharing.html

Zeeshan Hassan Memon
  • 8,105
  • 4
  • 43
  • 57
Manmeet Singh
  • 430
  • 5
  • 3
  • 6
    This isn't a `cors` file, but a `cors` subresource. So for those who try to dump a file named `cors` in your bucket, that won't work. (I tried this myself.) – Michael Mior May 14 '13 at 13:00
  • 7
    Just a note on the cors for S3. When applying a policy, files already in the bucket are NOT updated. So make sure you apply a CORS policy to only new buckets, or re-add the content after applying the policy. – samsamm777 Jul 24 '14 at 13:37
  • @samsamm777 I am facing this issue. I am not able to update existing files in my s3 bucket. How can I update my existing files in the s3 bucket with CORS? – Tushar Kulkarni May 03 '19 at 10:37
6

Searched a lot - This is the sample solution:

http://blog.bignerdranch.com/1670-upload-directly-to-amazon-s3-with-support-for-cors/

(Add cors on bucket permissions tab)

<?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>
griffon vulture
  • 6,594
  • 6
  • 36
  • 57
5

We had a similar problem, but not with GET but with presigned S3 POST. I thought this may be helpful for someone googling this issue.

in some browsers Dropzone.js lib was not able to upload images directly to S3 bucket (presigned S3 POST). Weird part was that this was happening on some computers all the time and on some one out of twenty tries.

On one computer we manage to capture the error in Firefox Debugger (network tab)

Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at https://s3-eu-west-1.amazonaws.com/pobble.com-browser-uploads-production. (Reason: CORS header 'Access-Control-Allow-Origin' missing).

Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at https://s3-eu-west-1.amazonaws.com/pobble.com-browser-uploads-production. (Reason: CORS request failed).

Updating the S3 bucket CORS to this worked for us:

<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
    <CORSRule>
        <AllowedOrigin>http://www.myapp.com</AllowedOrigin>
        <AllowedMethod>GET</AllowedMethod>
        <AllowedMethod>POST</AllowedMethod>
        <AllowedMethod>PUT</AllowedMethod>
        <AllowedHeader>*</AllowedHeader>
        <ExposeHeader>Accept-Ranges</ExposeHeader>
        <ExposeHeader>Content-Range</ExposeHeader>
        <ExposeHeader>Content-Encoding</ExposeHeader>
        <ExposeHeader>Content-Length</ExposeHeader>
        <ExposeHeader>Access-Control-Allow-Origin</ExposeHeader>
    </CORSRule>
    <CORSRule>
        <AllowedOrigin>https://www.app.com</AllowedOrigin>
        <AllowedMethod>GET</AllowedMethod>
        <AllowedMethod>POST</AllowedMethod>
        <AllowedMethod>PUT</AllowedMethod>
        <AllowedHeader>*</AllowedHeader>
        <ExposeHeader>Accept-Ranges</ExposeHeader>
        <ExposeHeader>Content-Range</ExposeHeader>
        <ExposeHeader>Content-Encoding</ExposeHeader>
        <ExposeHeader>Content-Length</ExposeHeader>
        <ExposeHeader>Access-Control-Allow-Origin</ExposeHeader>
    </CORSRule>
</CORSConfiguration>

important part is the <ExposeHeader>Access-Control-Allow-Origin</ExposeHeader> thanks to this S3 is exposing response header OPTIONS and POST

enter image description here

Collaborative work of @anas-alaoui, @joserose & @equivalent

Community
  • 1
  • 1
equivalent8
  • 13,754
  • 8
  • 81
  • 109
3

You can use a jsonp request instead of json. Here are the details. http://api.jquery.com/jQuery.ajax/

Joshua Dwire
  • 5,415
  • 5
  • 29
  • 50
Aatif Farooq
  • 1,828
  • 1
  • 13
  • 15
  • 2
    Yes but please see the Amazon CORS docs as well as this is a (recent) Amazon-supported option for selective enabling of domains. – Dean Radcliffe Dec 17 '12 at 21:53
1

I was struggling with the same sort of issue. only difference is i wanted to pull a file with Ajax from my S3 and load it into a site.

After a lot of searching i ended up adding this option to my Ajax request.

xhrFields: { withCredentials: true },

Worked like a charm, as long as you have the CORSConfiguration to allow all.

hope it helps.

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

This CORS configuration worked like a charm

Željko Šević
  • 3,743
  • 2
  • 26
  • 23
0

This is my Tip from: https://github.com/mozilla/pdf.js/issues/3150

<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
    <CORSRule>
        <AllowedOrigin>*</AllowedOrigin>
        <AllowedMethod>GET</AllowedMethod>
        <AllowedHeader>*</AllowedHeader>
        <ExposeHeader>Accept-Ranges</ExposeHeader>
        <ExposeHeader>Content-Range</ExposeHeader>
        <ExposeHeader>Content-Encoding</ExposeHeader>
        <ExposeHeader>Content-Length</ExposeHeader>
    </CORSRule>
</CORSConfiguration>
sev
  • 1
0

You may want to increase the MAX AGE configuration if you have larger files that will take longer to download, or they may cut off early. Media hosting etc will need this. My config for wildcard access (any domain) was 10000 seconds max, which should be safely longer than anyone needs to download my files even on a bad connection:

<?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>10000</MaxAgeSeconds>
    <AllowedHeader>*</AllowedHeader>
</CORSRule>
</CORSConfiguration>
OG Sean
  • 971
  • 8
  • 18
0

For anyone struggling with this issue, as others say you must force S3 to respond with CORS headers by adding these lines to your CORS configuration:

<AllowedOrigin>http://*</AllowedOrigin>
<AllowedOrigin>https://*</AllowedOrigin>

BUT, you then must clear your browser file cache as the old headers on the requested resource are stored. In Chrome, find the Clear Browsing Data option and then choose to clear the file cache. A hard reload will not clear certain files. If you prefer to only clear the file cache only for the current site, this answer explains how to do just that.

This was the gotcha for me.

0

For my case, I want to GET some resources from a bucket "myBucket".

On the S3 client side, AWS S3 now support JSON to configure CORS policies [ref]

Bucket Policy:

[
    {
        "AllowedHeaders": [
            "*",
            "x-amz-*"
        ],
        "AllowedMethods": [
            "GET",
            "HEAD"
        ],
        "AllowedOrigins": [
            "*"
        ],
        "ExposeHeaders": []
    }
]

On server-side / client side (JQUERY Ajax)

$.ajax({
    type: "GET", 
    url: "https://myBucket/myObject",
});​​​​​​​​​​​​​​​

Try it!, hope it helps!

Franco Gil
  • 323
  • 3
  • 11
  • The impact will be applied around 2-10 minutes after set the CORS policy. At least I have to wait almost 5 minutes to get the bucket object through an AJAX request. – Franco Gil Nov 12 '20 at 03:44