Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

^11.1.2 - Using cdn for assets results in CORS error only for some css files not all #34225

Open
kristijorgji opened this issue Feb 11, 2022 · 26 comments
Labels
bug Issue was opened via the bug report template.

Comments

@kristijorgji
Copy link

kristijorgji commented Feb 11, 2022

Run next info (available from version 12.0.8 and up)

"next": "^11.1.2",

What version of Next.js are you using?

"next": "^11.1.2",

What version of Node.js are you using?

15.0.1

What browser are you using?

Chrome

What operating system are you using?

macOS

How are you deploying your application?

next start in aws

Describe the Bug

I am deploying my nextjs application in a single ec2 instance in aws.
I deploy the next assets _next/static in a s3 bucket, and they are served via cloudfront

in next.config.js i put correctly assetPrefix to my cdn:
NOTE: I replaced client domain with domain.com for privacy reason, everything else is documented with real data from the bug scenario.

assetPrefix:: 'https://cdn.dev.domain.com'

The above config works fine, on deployment app tries to get files from cdn and works for 95 % of js/css.

Issue is that I get cors error for only some CSS which is crazy!

Most of page deployed works fine can load js/css in my cdn _next/static folder, but some css fail and this causes particular routes not to load!!! and user face silent errors

screenshoot of network tab
Screenshot 2022-02-11 at 13 19 38

shows that some css are loading some no. .js files load fine from the cdn. My domain is allowed in s3 bucket cors policies and is getting files correctly most of them I mean, as some css don't load.

Error in console is

Access to fetch at 'https://cdn.dev.domain.com/_next/static/css/dfed990485bdfd23f3fe.css' from origin 'https://web.dev.domain.com' 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.

I notice that for working css fetches, next sends cors headers correctly. I copied one chrome network request as curl and post below, that is working fine.

  curl 'https://cdn.dev.domain.com/_next/static/css/ffe628ef00744e353e72.css' \
  -H 'authority: cdn.dev.domain.com' \
  -H 'pragma: no-cache' \
  -H 'cache-control: no-cache' \
  -H 'sec-ch-ua: " Not A;Brand";v="99", "Chromium";v="98", "Google Chrome";v="98"' \
  -H 'sec-ch-ua-mobile: ?0' \
  -H 'user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.80 Safari/537.36' \
  -H 'sec-ch-ua-platform: "macOS"' \
  -H 'accept: */*' \
  -H 'origin: https://web.dev.domain.com' \
  -H 'sec-fetch-site: same-site' \
  -H 'sec-fetch-mode: cors' \
  -H 'sec-fetch-dest: empty' \
  -H 'referer: https://web.dev.domain.com/' \
  -H 'accept-language: en-US,en;q=0.9' \
  --compressed

other times I see the cors error in network tab and this requst type ( no cors headers at all added by next load initiator somewhere at main-70dd238….js:1)
Below request in screenshoot resulted in CORS error that I posted above

Screenshot 2022-02-11 at 15 27 41

Expected Behavior

NextJS should be consistent, if it manages to load all js files and 95% of css over CDN , while sending same request headers I expect everything to work fine load all route assets 100% correctly and avoid silent errors like this.

To Reproduce

  1. Change assetPrefix in next.config.js to some cdn url that is using as source a s3 bucket
  2. upload .next/static to one s3 bucket _next/static

yarn build && yarn start the next app in a domain that is subdomain of the cdn domain.
S3 bucket allows the website domain as CORS origin

What I tried already

  1. in next.config.js I added crossOrigin: 'anonymous', after a lot of online reasearch. Then build deployed and started, unfortunately did not help. Actually cors was broken totally after this change no asset could be loaded
  2. Solution provided here CORS error fetching CSS on S3 asset host while shallow routing #21513 (comment) to change cloudfront s3 origin to add header origin *. Tried and did not work (after invalidating all cache of course, also with uploading assets to new folder as well)
@kristijorgji kristijorgji added the bug Issue was opened via the bug report template. label Feb 11, 2022
@kristijorgji kristijorgji changed the title Using cdn for assets results in CORS error only for some css files not all ^11.1.2 - Using cdn for assets results in CORS error only for some css files not all Feb 11, 2022
@jschlechtehomer
Copy link

I'm seeing this also (with 11.1.3). Any luck?

@balazsorban44
Copy link
Member

Could any of you try with next@canary and see if the issue still reproduces? 🙏

@jschlechtehomer
Copy link

jschlechtehomer commented Feb 22, 2022

I haven't tried canary yet, but I did upgrade to ^12.0.10 and still see the issue.

Specifically it seems to be successfully fetching the css resources when they are included in the html (from the initial server side render, this is CORS exempt) but then client side navigations via router trigger a javascript fetch for the css resource, and then the CORS is rejected (javascript triggered fetch of css is not CORS exempt).

What's odd to me is that it seems like the fetch is somehow omitting the Origin header.

S3 typically omits the CORS response headers if the Origin request header is absent. If I run curl -v -H 'Origin: <anything>' <my_cdn_url> then the response headers include the cross origin headers:

< access-control-allow-origin: *
< access-control-allow-methods: GET, HEAD
< access-control-expose-headers: ETag
< access-control-max-age: 3000

This confirms that S3/CDN are suitably configured, and suggests that somehow Origin is being omitted or removed. The browser network logs, consistent with @kristijorgji's original post, show no CORS response headers, nor any request headers.

@akselinurmio
Copy link

I can confirm this issue. We are also using S3 for serving static assets. S3 is correctly adding CORS headers, but it requires Origin header to be present. Could there be some asset that's being fetched without an Origin header?

Here's the error message Chrome outputs to console on our site:

Access to fetch at 'https://areena-web-items.test.ylestatic.fi/0.3.1863-items-fade-bg/_next/static/css/6878b397cb769138.css' from origin 'https://areena-test.yle.fi' 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.

@jschlechtehomer
Copy link

jschlechtehomer commented Apr 12, 2022

It's not my favorite solution, but our CDN is quite configurable so I ended up custom scripting a solution to workaround this. I just modified the responses to ensure that the CORs headers are included even in the absence of request Origin header.

I would still love to understand the root cause of the missing header, and see a fix if it's a next bug.

@sidreddyinsider
Copy link

@ijjk can you please look at this.
@jschlechtehomer @akselinurmio we are facing similar issue.
Patterns we found.
#1 Incongnito mode in all browsers work fine.
#2 This happens when transitioning from SSR page to static html page, css file fetch breaks and this leads to full page reload. So any redux state we are relying on goes away. Our application is breaking and this is terrible.
#3 When i do a hard refresh, the problem goes away and then comes back. This has to do with service worker caching returning opaque response.

solutions tried:
set next_config -> crossOrigin : anonymous/with-credentials. Did not work.

Our CDN is fine, all other files are downloaded and only a few css files where transition is from ssr to static html pages is creating an issue. Also we see no issue with js files, they are being downloaded.

@sidreddyinsider
Copy link

@jschlechtehomer @ijjk any findings?

@jschlechtehomer
Copy link

@sidreddyinsider nope; we just moved on with the CDN altering the headers to bridge the gap.

@samueldusek
Copy link
Contributor

I am using "next": "12.1.7-canary.2" in my project and I see the same error.

image

Is there any progress on this issue?

@drgx
Copy link

drgx commented Jun 7, 2022

I believe this is not next js issue. It is CDN configuration.
You need to add the CDN header to add "Access-control-allow-origin" header.

Note: Using * for simplicity.

access-control-allow-origin: *

if you are using the AWS cloudfront you can go to to cloudfront ->Behaviors -> Response headers policy -> SimpleCors

image

Good luck

@atulpe
Copy link

atulpe commented Nov 23, 2022

@Lumuy
Copy link

Lumuy commented Feb 23, 2023

Any luck for this? I meet the same issue when I upgrade nextjs to version 13

----update-----

In my case, we use Heroku add on EDGE for CDN
Screenshot 2023-02-28 at 16 09 54
After click the Invalidate button and add (access-control-allow-origin: *), it works

@vinodmmm
Copy link

vinodmmm commented Jul 6, 2023

I believe this is not next js issue. It is CDN configuration. You need to add the CDN header to add "Access-control-allow-origin" header.

Note: Using * for simplicity.

access-control-allow-origin: *

if you are using the AWS cloudfront you can go to to cloudfront ->Behaviors -> Response headers policy -> SimpleCors

image

Good luck

This configuration was already there in my case but didn't working at all. So I created a custom policy to allow all origins and few methods. This helped fixing the issue.

@antho1jp
Copy link

We are having the same issue but with multiple 3rd party vendors. It's kind of difficult to reach out to all the vendors and tell them to fix their CDN settings. This should be something we can control in the Next config somehow.

@joekur
Copy link

joekur commented Aug 31, 2023

This may be a separate bug, but at least related:

I've encountered the same CORS issue as described above - next app is hosted on stitchfix.com, assets are on assets.stitchfix.com. I see a read from disk, and then a CORS error for the same .css asset initiated from javascript:

Screenshot_2023-08-31_at_4_19_10_PM

This looks to be here:

async handleRouteInfoError(

The behavior I then see is an infinite refresh of the current page. I'm guessing this is happening a few lines later (isAssetError):

if (isAssetError(err) || loadErrorFail) {
Router.events.emit('routeChangeError', err, as, routeProps)
// If we can't load the page it could be one of following reasons
// 1. Page doesn't exists
// 2. Page does exist in a different zone
// 3. Internal error while loading the page
// So, doing a hard reload is the proper way to deal with this.
handleHardNavigation({
url: as,
router: this,
})

It's additionally perplexing because I see this which supposedly should prevent a navigation to the same URL:

// ensure we don't trigger a hard navigation to the same
// URL as this can end up with an infinite refresh
if (url === addBasePath(addLocale(router.asPath, router.locale))) {
throw new Error(
`Invariant: attempted to hard navigate to the same URL ${url} ${location.href}`
)
}

This all started with the introduction of a middleware. I'm not sure if next thinks middleware should run on this asset request, even though it is from a different (sub-)domain.

@y122972
Copy link

y122972 commented Nov 8, 2023

This may be a separate bug, but at least related:

I've encountered the same CORS issue as described above - next app is hosted on stitchfix.com, assets are on assets.stitchfix.com. I see a read from disk, and then a CORS error for the same .css asset initiated from javascript:

Screenshot_2023-08-31_at_4_19_10_PM

This looks to be here:

async handleRouteInfoError(

The behavior I then see is an infinite refresh of the current page. I'm guessing this is happening a few lines later (isAssetError):

if (isAssetError(err) || loadErrorFail) {
Router.events.emit('routeChangeError', err, as, routeProps)
// If we can't load the page it could be one of following reasons
// 1. Page doesn't exists
// 2. Page does exist in a different zone
// 3. Internal error while loading the page
// So, doing a hard reload is the proper way to deal with this.
handleHardNavigation({
url: as,
router: this,
})

It's additionally perplexing because I see this which supposedly should prevent a navigation to the same URL:

// ensure we don't trigger a hard navigation to the same
// URL as this can end up with an infinite refresh
if (url === addBasePath(addLocale(router.asPath, router.locale))) {
throw new Error(
`Invariant: attempted to hard navigate to the same URL ${url} ${location.href}`
)
}

This all started with the introduction of a middleware. I'm not sure if next thinks middleware should run on this asset request, even though it is from a different (sub-)domain.

It seems like a bug. Any solution?

@y122972
Copy link

y122972 commented Nov 9, 2023

This may be a separate bug, but at least related:
I've encountered the same CORS issue as described above - next app is hosted on stitchfix.com, assets are on assets.stitchfix.com. I see a read from disk, and then a CORS error for the same .css asset initiated from javascript:
Screenshot_2023-08-31_at_4_19_10_PM
This looks to be here:

async handleRouteInfoError(

The behavior I then see is an infinite refresh of the current page. I'm guessing this is happening a few lines later (isAssetError):

if (isAssetError(err) || loadErrorFail) {
Router.events.emit('routeChangeError', err, as, routeProps)
// If we can't load the page it could be one of following reasons
// 1. Page doesn't exists
// 2. Page does exist in a different zone
// 3. Internal error while loading the page
// So, doing a hard reload is the proper way to deal with this.
handleHardNavigation({
url: as,
router: this,
})

It's additionally perplexing because I see this which supposedly should prevent a navigation to the same URL:

// ensure we don't trigger a hard navigation to the same
// URL as this can end up with an infinite refresh
if (url === addBasePath(addLocale(router.asPath, router.locale))) {
throw new Error(
`Invariant: attempted to hard navigate to the same URL ${url} ${location.href}`
)
}

This all started with the introduction of a middleware. I'm not sure if next thinks middleware should run on this asset request, even though it is from a different (sub-)domain.

It seems like a bug. Any solution?

// next.config.js
module.exports = { crossOrigin: "anonymous" }

@aryanet
Copy link

aryanet commented Nov 9, 2023

Hi There,

We upgraded from Next 12 to Next 14, and started experiencing the same problem in our staging environment, so we have not released to prod yet.

We did not change our CDN configuration and it was working with its current configuration for several months and Next 12.

From the symptoms I have investigated when some _next/.js files fails due to CORS, those particular requests are missing the "Origin" request header which when absent makes the CDN config to not sent Access-Control-Allow-Origin in response header.

I have read all the above comments and my issue is exactly similar with some assets not loading from CDN due to CORS.

I think there is bug with Next or something new config we don't know. But if I roll back to our old version of Next, the problem goes away.

@aryanet
Copy link

aryanet commented Nov 9, 2023

I believe this is not next js issue. It is CDN configuration. You need to add the CDN header to add "Access-control-allow-origin" header.

Note: Using * for simplicity.

access-control-allow-origin: *

if you are using the AWS cloudfront you can go to to cloudfront ->Behaviors -> Response headers policy -> SimpleCors

image

Good luck

Your suggestion is a workaround to the problem which forces a header from CDN, but this is not ideal. If CDN was the root cause, then why rolling back to old Next version solves the problem?

As multiple people mentioned, they have not changed their CDN configuration and this issue came up after upgrader. Hence the skepticism about it being a bug.

@y122972
Copy link

y122972 commented Nov 14, 2023

This may be a separate bug, but at least related:
I've encountered the same CORS issue as described above - next app is hosted on stitchfix.com, assets are on assets.stitchfix.com. I see a read from disk, and then a CORS error for the same .css asset initiated from javascript:
Screenshot_2023-08-31_at_4_19_10_PM
This looks to be here:

async handleRouteInfoError(

The behavior I then see is an infinite refresh of the current page. I'm guessing this is happening a few lines later (isAssetError):

if (isAssetError(err) || loadErrorFail) {
Router.events.emit('routeChangeError', err, as, routeProps)
// If we can't load the page it could be one of following reasons
// 1. Page doesn't exists
// 2. Page does exist in a different zone
// 3. Internal error while loading the page
// So, doing a hard reload is the proper way to deal with this.
handleHardNavigation({
url: as,
router: this,
})

It's additionally perplexing because I see this which supposedly should prevent a navigation to the same URL:

// ensure we don't trigger a hard navigation to the same
// URL as this can end up with an infinite refresh
if (url === addBasePath(addLocale(router.asPath, router.locale))) {
throw new Error(
`Invariant: attempted to hard navigate to the same URL ${url} ${location.href}`
)
}

This all started with the introduction of a middleware. I'm not sure if next thinks middleware should run on this asset request, even though it is from a different (sub-)domain.

It seems like a bug. Any solution?

// next.config.js
module.exports = { crossOrigin: "anonymous" }

This issue seems to have been fixed in some latest version:

crossOrigin: nextConfig.crossOrigin || '',

in 11.1.4

const crossOrigin = config.crossOrigin

@akbortoli
Copy link

@ild0tt0re any news on your PR? Is there a way to get around this issue without your fix? We are also having this issue...

@akbortoli
Copy link

We are on 14.0.3 and still having this issue.

@ild0tt0re
Copy link

@ild0tt0re any news on your PR? Is there a way to get around this issue without your fix? We are also having this issue...

No, please upvote it here #58200

In the meantime you can use patch subcommand of your package manager like pnpm patch next@version

@martijnhjk
Copy link

@ild0tt0re apart from upvoting is there anything else we can do to gain some momentum on your PR? It would be great to get it fixed...

@setoelkahfi
Copy link

Got this problem recently. I added the:

    assetPrefix: isProd ? 'https://cdnndc.b-cdn.net' : undefined,
    crossOrigin: 'anonymous'

I'm using "next": "^13.5.6" with nginx. I added the add_header Access-Control-Allow-Origin "https://cdnndc.b-cdn.net"; in the server block and location /_next/static still no luck. Any pointers?

@setoelkahfi
Copy link

Got this problem recently. I added the:

    assetPrefix: isProd ? 'https://cdnndc.b-cdn.net' : undefined,
    crossOrigin: 'anonymous'

I'm using "next": "^13.5.6" with nginx. I added the add_header Access-Control-Allow-Origin "https://cdnndc.b-cdn.net"; in the server block and location /_next/static still no luck. Any pointers?

Nevermind. It's my cdn service issue: I need to add .js extension in the list of additional header settings.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Issue was opened via the bug report template.
Projects
None yet
Development

No branches or pull requests