- Published on
Solving A CORS Issue In Chrome When Serving From Browser Cache
- Authors
- Name
- Anthony Mineo
- @mineo27
CORS issues are always a treat! Especially when the issue appeared to be random and only affects Chromium-based browsers.
The Setup
I wrote a static script file hosted in an S3 bucket and then served via CloudFront on a different subdomain. That script also dynamically loaded another script.
So the call stack looked something like this:
- website.com/page.html
- static.website.com/script1.js
- static.website.com/script2.js
- static.website.com/script1.js
The S3 Bucket permissions had CORS configured like this:
[
{
"AllowedHeaders": [
"*"
],
"AllowedMethods": [
"GET",
"HEAD"
],
"AllowedOrigins": [
"*"
],
"ExposeHeaders": [],
"MaxAgeSeconds": 3600
}
]
Nothing crazy. We're just allowing the GET and HEAD methods, letting any origin access it, and setting a max-age.
The CloudFront distribution also had the correct headers whitelisted:
- Access-Control-Request-Headers
- Access-Control-Request-Method
- Origin
The Problem
It appeared that everything was working fine in FireFox, Safari, and Chrome. However, in Chrome, when the browser served the script file from its cache, I was getting the classic CORS error:
"No `access-control-allow-origin` header is present on the requested resource."
As it turns out, the cached version does not contain the CORS headers in Chrome. It drops the request as Access-Control-Allow-Origin violation
since the location is from the (disk cache) instead of static.website.com
.
The Solution
There are few ways to solve this.
By far, the quickest way is adding the attribute crossorigin="anonymous"
to the script tag—the crossorigin attribute, among other things, hints to the browser that it shouldn't cache the CORS headers.
A possibly more involved approach, depending on your setup, is to have the server respond with a Vary: Origin
header. If you're using something like Nginx, this is pretty simple as you can add a response header. Adding a response header to CloudFront is a bit tedious as you need to use Lambda@Edge, which to me felt like overkill.
In the end, I formatted my script tag like <script src="https://static.website.com/script1.js" crossorigin="anonymous">
and Chrome's CORS issue when serving from cache went away.
Hope this helps! Hit me up on Twitter: @Mineo27 if you have any issues/questions.