简体   繁体   中英

Fetching an image from S3 bucket is not working because of CORS

The problem is i am getting the cors error (response header does not contain Access-Control-Allow-Origin ) when i try to fetch using fetch API. Here is my cors config in S3 -

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

The code can be found here - https://codepen.io/sourov0805045/pen/OKVBXM?editors=1111

I have checked the response header and saw it does not contain the Allow-Access-Control-Origin header.

But this works properly if i add this in a <img> tag which is quite puzzling. That time there is no Access-Control-Allow-Origin in the response header as well but the image loads properly.

A have tried the same with axios with no effect.

Please let me know you suggestion on how can i solve this problem.

First start off by removing un-necessary variables: use cURL from the command line.

Step 1: Issue the pre-flight OPTIONS request:

curl -H "Origin: http://example.com" \
      -H "Access-Control-Request-Method: GET" \
      -H "Access-Control-Request-Headers: X-Requested-With" \
      -X OPTIONS --verbose \
      'https://twisker-s3-files.s3.us-east-2.amazonaws.com/files/-GxfyX_dZ-6313383.jpg'

The response headers you are looking for in the output are:

...
< Access-Control-Allow-Origin: *
< Access-Control-Allow-Methods: GET, POST, PUT, HEAD, DELETE
< Access-Control-Allow-Headers: x-requested-with
< Vary: Origin, Access-Control-Request-Headers, Access-Control-Request-Method
...

Step 2: Issue the GET request:

~ $ curl --head 'https://twisker-s3-files.s3.us-east-2.amazonaws.com/files/-GxfyX_dZ-6313383.jpg' -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36' -H 'Referer: https://cdpn.io/boomboom/v2/index.html?editors=1111&key=iFrameKey-a88ea9ee-51a6-0ae2-7350-951a5b1e4e56' -H 'Origin: https://cdpn.io' --compressed

Here is the response:

HTTP/1.1 200 OK
x-amz-id-2: 9D3J5BnHo7YocXQicso+eQAC/PlyoOMpc5QXd+G77HMtWTOd8kYymcJnQ0T8J7tqXetMZgVO8Rw=
x-amz-request-id: 6CE1579D5B039163
Date: Thu, 25 Jul 2019 02:18:41 GMT
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET, POST, PUT, HEAD, DELETE
Vary: Origin, Access-Control-Request-Headers, Access-Control-Request-Method
Last-Modified: Wed, 26 Jun 2019 19:18:40 GMT
ETag: "8e26c03714ab4d8e185c29b1c04639f0"
Accept-Ranges: bytes
Content-Type: application/octet-stream
Content-Length: 1573767
Server: AmazonS3

Few things of note:

  1. Access-Control-Allow-Origin and Access-Control-Allow-Methods exist
  2. Their values look to be correct, so CORS should work for you (it did for me on your URL)

https://www.test-cors.org can be used to test CORS requests. It gives some output on each phase of the request.

Last, browsers are very aggressive on caching the pre-flight OPTIONS request. So if you are looking at chrome network debug tools, you may not see the pre-flight OPTIONS request. Sometimes re-starting chrome will clear the OPTIONS cache, sometimes it requires clearing all the browser cache.

This caching can be problematic if you don't have CORS correctly configured server side, and the browser caches the response. Ex: you don't allow GET when you initially configure CORS. You issue the OPTIONS request and the browser caches the response, blocking future GET requests.

Since S3 links start with // it will use the current protocol to make request. If you have http://localhost AWS won't allow you to make request over http, even if the AllowedOrigins is * .

Prefix URL with https in axios url param, and it should work.

The issue is with the way AllowedOrigins value configuration is perceived by the S3 internally. Try giving https://*.yourdomain.com instead of https://something.yourdomain.com in your S3 bucket level CORS Configuration, Here is my sample configuration and it works!

[
    {
        "AllowedHeaders": [
            "*"
        ],
        "AllowedMethods": [
            "GET",
            "PUT",
            "POST",
            "DELETE",
            "HEAD"
        ],
        "AllowedOrigins": [
            "https://*.yourdomain.com"
        ],
        "ExposeHeaders": [
            "x-amz-server-side-encryption",
            "x-amz-request-id",
            "x-amz-id-2"
        ],
        "MaxAgeSeconds": 3000
    }
]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM