admin 管理员组

文章数量: 1086019

I’m using Next.js (front-end) at and serving images from via Amazon S3 + CloudFront. Despite having set up CORS, my browser still reports a CORS error when I try to load images. The preflight (OPTIONS) request looks successful in the logs from cURL, but the actual GET request triggers a CORS error in the browser console.

Details

Client

I'm using Photo-Sphere-Viewer to render 360 AVIF images. Just like this:

panoramaViewer = new Viewer({
    container: viewerElement,
    panorama: imageURL,
    requestHeaders: {
        "Sec-Fetch-Mode": "no-cors",
        Origin: ";,
    },
    withCredentials: true,
});

You can see all the other options here in the documentation, but the CORS related ones are withCredentials and requestHeaders. I played adding and removing the credentials, adding and removing headers. Many different combinations.

Anyways, at the end what this does it's just invoking a JS fetch (which also doesn't work). So in summary, the problem it's just accessing CORS through fetch, although I mention the PSV library in case someone seems something related.

Server

This is my CORS configuration on S3 Bucket

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

I can't add the OPTIONS method, as specified by S3 docs. But I think they handle them by default.

CloudFront is connected correctly (as it displays the images correctly when accessing outside the browser). And the relevant CORS configuration is on this behavior:

The 2 CORS related policies are the default ones included by CloudFront:

CORS-S3Origin:

Managed-SimpleCORS:

So in summary, everything should be being forwarded as expected. After each CloudFormation change, I create an invalidation for /*, so nothing should be cached on CF side.

In this CORS test page I see it works as expected.

But when invoking it through my application I see the following error.

Access to fetch at '.avif' from origin '' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.

When I access it through cURL it works:

curl -I -H "Origin: ; .avif

Response:

HTTP/2 200
content-type: image/avif
content-length: 1062925
date: Thu, 27 Mar 2025 17:48:45 GMT
access-control-allow-origin: *
access-control-allow-methods: GET, HEAD
last-modified: Wed, 05 Feb 2025 12:47:36 GMT
etag: "3f4ca06ef766a9cb71e287490fc05aa9"
x-amz-server-side-encryption: AES256
accept-ranges: bytes
server: AmazonS3
x-cache: Hit from cloudfront
via: 1.1 90b76e653c2ec3d955102c951a3c0250.cloudfront (CloudFront)
x-amz-cf-pop: GRU1-C1
x-amz-cf-id: KvVQfT7aiMgJKHrtvFknyeimDWfD0ZkQJo_ktWaF3tlS_EThdlxnlg==
age: 21658

So I'm really lost on what's the error. I know it's probably a misconfiguration somewhere, but can't see where!

I’m using Next.js (front-end) at https://toscanini.me and serving images from https://images.toscanini.me via Amazon S3 + CloudFront. Despite having set up CORS, my browser still reports a CORS error when I try to load images. The preflight (OPTIONS) request looks successful in the logs from cURL, but the actual GET request triggers a CORS error in the browser console.

Details

Client

I'm using Photo-Sphere-Viewer to render 360 AVIF images. Just like this:

panoramaViewer = new Viewer({
    container: viewerElement,
    panorama: imageURL,
    requestHeaders: {
        "Sec-Fetch-Mode": "no-cors",
        Origin: "https://toscanini.me",
    },
    withCredentials: true,
});

You can see all the other options here in the documentation, but the CORS related ones are withCredentials and requestHeaders. I played adding and removing the credentials, adding and removing headers. Many different combinations.

Anyways, at the end what this does it's just invoking a JS fetch (which also doesn't work). So in summary, the problem it's just accessing CORS through fetch, although I mention the PSV library in case someone seems something related.

Server

This is my CORS configuration on S3 Bucket

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

I can't add the OPTIONS method, as specified by S3 docs. But I think they handle them by default.

CloudFront is connected correctly (as it displays the images correctly when accessing outside the browser). And the relevant CORS configuration is on this behavior:

The 2 CORS related policies are the default ones included by CloudFront:

CORS-S3Origin:

Managed-SimpleCORS:

So in summary, everything should be being forwarded as expected. After each CloudFormation change, I create an invalidation for /*, so nothing should be cached on CF side.

In this CORS test page I see it works as expected.

But when invoking it through my application I see the following error.

Access to fetch at 'https://images.toscanini.me/travel/europa-2023/barcelona/palau-musica-catalana-techo-del-teatro.avif' from origin 'https://toscanini.me' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.

When I access it through cURL it works:

curl -I -H "Origin: https://toscanini.me" https://images.toscanini.me/travel/europa-2023/barcelona/palau-musica-catalana-techo-del-teatro.avif

Response:

HTTP/2 200
content-type: image/avif
content-length: 1062925
date: Thu, 27 Mar 2025 17:48:45 GMT
access-control-allow-origin: *
access-control-allow-methods: GET, HEAD
last-modified: Wed, 05 Feb 2025 12:47:36 GMT
etag: "3f4ca06ef766a9cb71e287490fc05aa9"
x-amz-server-side-encryption: AES256
accept-ranges: bytes
server: AmazonS3
x-cache: Hit from cloudfront
via: 1.1 90b76e653c2ec3d955102c951a3c0250.cloudfront (CloudFront)
x-amz-cf-pop: GRU1-C1
x-amz-cf-id: KvVQfT7aiMgJKHrtvFknyeimDWfD0ZkQJo_ktWaF3tlS_EThdlxnlg==
age: 21658

So I'm really lost on what's the error. I know it's probably a misconfiguration somewhere, but can't see where!

Share Improve this question edited Apr 3 at 11:02 Santiago Toscanini asked Mar 27 at 23:52 Santiago ToscaniniSantiago Toscanini 3261 gold badge5 silver badges11 bronze badges 11
  • What do you mean you can't add OPTIONS method? – Caldazar Commented Mar 28 at 21:41
  • @Caldazar The S3 CORS docs specify which methods you can include on the AllowedMethods, and OPTIONS is not there, because I think it’s always handled by them docs.aws.amazon/AmazonS3/latest/userguide/… – Santiago Toscanini Commented Mar 30 at 10:55
  • 1 Could you try the managed response headers policy - CORS-With-Preflight? Since the response header policy SimpleCORS has stricter limitations, it is not applicable in most scenarios. – richard02110 Commented Apr 1 at 22:05
  • Is "Sec-Fetch-Mode": "no-cors" required? The curl command you used doesn't have it. Have you tried removing it in your code? – vht981230 Commented Apr 2 at 4:11
  • Is it expected that your AVIF file is returning a 403 error? The CORS test page that you linked indeed say "the URL will work with CORS", however it doesn't account for the 403 status code. Here is the result from my CORS tester: corsfix/tools/… – reynaldi Commented Apr 2 at 5:35
 |  Show 6 more comments

2 Answers 2

Reset to default 0 +50

Your CloudFront configuration is already working well and supports CORS request.

It's the way you are loading the panorama viewer, remove the requestHeaders and withCredentials field, so your code becomes

panoramaViewer = new Viewer({
    container: viewerElement,
    panorama: imageURL,
});

The requestHeaders isn't doing anything in this case because both Sec-Fetch-Mode and Origin are forbidden request headers, meaning they can't be modified.

As for the withCredentials, you don't need this, since you are not sending any credentials (Authorization or Cookie headers). Plus, having the Access-Control-Allow-Origin set to *, will trigger an error making your request fail.

Failed to load resource: Cannot use wildcard in Access-Control-Allow-Origin when credentials flag is true.

Here is a working demo with the correct code showing the panorama

  • demo: https://santiago-psv.pages.dev
  • code: https://github/reynaldichernando/santiago-psv

I believe the URL you are requesting is already cached with the CORS response and you need to invalidate it first.

Your CloudFront configuration shows that you are not caching "OPTIONS" methods, so the preflight calls will be accessing non-cached version of the URLs - allowing the CORS test site to return a successful response, since it never executes the actual GET request. However, GET is cached by default, so if you tested this access before setting these header configurations on S3/CloudFront, you would be still getting the cached response.

Update 04/04/2025:

Based on Santiago's update, above comment is no longer valid, but leaving it here in case it becomes useful to others.

The client-side fetch call appears to be working on your site as you can see below, so I believe your issue may be related to Next.JS SSR instead of AWS configurations (or headers you pass through in case you have a Next.JS middleware configuration).

Browser Fetch Call

本文标签: amazon web servicesCORS Issue with CloudFrontS3Stack Overflow