Safari: "Fetch API cannot load due to access control checks" after reload
Asked Answered
R

5

28

I experience some odd behavior in the CORS system of Safari. I have a POST request which I send from the JS Fetch API like this:

const res = await fetch('http://localhost:8888/myPath', {
  method: 'POST',
  mode: 'cors',
  headers: {
    'Content-Type': 'application/json'
  },
  body: JSON.stringify(body)
});

According to the network monitor of Safari, the request header looks like this:

POST /myPath HTTP/1.1
Accept: */*
Content-Type: application/json
Origin: http://my.domain.com
Content-Length: 335
Accept-Language: en-gb
Host: localhost:8888
User-Agent: Mozilla/5.0...
Referer: http://my.domain.com
Accept-Encoding: gzip, deflate
Connection: keep-alive

and the following response comes from the server:

HTTP/1.1 200 OK
Date: Tue, 28 Jul 2020 19:15:45 GMT
Vary: Origin
Content-Length: 4
Content-Type: application/json
Access-Control-Allow-Origin: http://my.domain.com
Server: uvicorn

Unfortunately, I don't have Wireshark on this machine and Safari does not show the preflight requests. So I don't know if any preflight happens and how that looks like.

Now the problem is: when I have a fresh browser session (e.g. with private mode) and access my document which triggers the fetch request, everything works. Only after reloading the page to send the CORS request again, I get "Fetch API cannot load due to access control checks" in the Safari console. So I presume, it has something to do with how Safari caches CORS requests/preflights.

In Firefox and Chrome, my CORS request works like a charm.

How can I solve this?

Raincoat answered 28/7, 2020 at 19:26 Comment(3)
I have this same issue. I cannot figure out if it's a Safari cache bug, or something that can be fixed with a CORSrule on the server. The fact that it only happens when Safari does a preflight CORS check on a cached resource makes me think its Safari.Paduasoy
In addition to the suggestion of the terminating forward slash, this post recommends adding the following header to all of responses that support CORS: Vary: Origin, Access-Control-Request-Headers, Access-Control-Request-Method #44800931Paduasoy
Could the issue be due to this "bug"/ignorance of the standard? bugs.webkit.org/show_bug.cgi?id=171934Triarchy
P
10

My suggestion, if you have control of your server is to add a terminating forward slash on your 'http://localhost:8888/myPath/'.

For example:

const res = await fetch('http://localhost:8888/myPath/', {
  method: 'POST',
  mode: 'cors',
  headers: {
    'Content-Type': 'application/json'
  },
  body: JSON.stringify(body)
});

Background

The reason I suggest this is I have the exact same problem. My variation of this issue is that it manifests as Safari failing its preflight CORS check on cached images, where the image src is a redirect (Canvas Instructure URL redirect to an AWS S3 bucket). With your example, I suspect it's related to your localhost vs. domain.com host name variation.

My Safari console error is that the host page's host domain is rejected by the image origin's domain. I expect yours is similar to this.

FetchEvent.respondWith received an error:
TypeError: Cross-origin redirection to <actual image source> 
denied by Cross-Origin Resource Sharing policy: 
Origin <hosted page containing the image src redirect to image source> 
is not allowed by Access-Control-Allow-Origin. 

The original CORS request is fine. It's only the preflight check on cached resource that fails. I'm hoping it's a Safari bug, because if it's a feature, Chrome & Firefox might follow with the weird behavior.

To duplicate my variation of the same issue:

  1. In Safari (v13.2 with file caching on, Desktop or iOS), Go to site https://cidilabs.instructure.com/courses/3/pages/upload-slash-embed-image-test. I do not control this public page, my apologies if it becomes a broken link. If you have access to a Canvas LMS, you can duplicate this page by uploading an image through the Canvas image upload tool to a module page. Canvas embeds uploaded images as a redirect link to an S3 bucket.
  2. Then refresh that page, to initiate a preflight CORS request on the cached image, to see the broken image link.

Workarounds Options:

  • Always open a private browser when using a page with an embedded CORS redirect image. The issue only happens when the image is cached. [Not a practical solution for users]
  • Add a terminating solidus (forward slash) to all cachable resources that are CORS redirect paths. The issue only happens when the redirect path looks like a file not a directory. [I'm torn about this being bad style for image src URL. But, because the image src is really a redirect and not really a file anyway, I think it's not totally bad to show it as a dir.] ** the most practical of the bad workarounds
  • Make the image src URL a DIFFERENT host than the page it's embedded in. The issue only seems to happen if the cached image src redirect URL is the same host as the web page. [This is so weird! Maybe, some crazy way Safari caches host page resources.]
  • Use FireFox or Chrome when going to a page with a CORS image src redirect. The issue only happens with Safari. [Terrible workaround, cuts out a lot of users]
Paduasoy answered 11/9, 2020 at 16:10 Comment(2)
Did you ever find a proper solution? I'm having a similar issue where iOS Safari (so far the only browser I have a problem with) is throwing Origin <url> is not allowed by Access-Control-Allow-Origin errors for cached images that were retrieved using crossorigin="anonymous". The frustrating part is this does not happen all the time and which images throw errors seems random. I'm using DigitalOcean Spaces, which is essentially an AWS S3 clone for cloud storage. I only set AllowedMethod to GET and HEAD for the cors rules and whitelist my host.Semaphore
Hi @user1087973, all set AllowedMethod to OPTIONS which is the preflight header. developer.mozilla.org/en-US/docs/Glossary/Preflight_requestPaduasoy
P
1

In my case, I was using http instead of https, Which made Safari not include my Authorization header.

Planer answered 26/6, 2022 at 17:13 Comment(0)
B
1

solved this by replacing localhost with 127.0.0.1 everywhere

Beckybecloud answered 21/11, 2023 at 8:58 Comment(0)
S
0

For me it was the Adblocker which broke this. I had a query parameter called "advertiser_id" which my Adblocker identified as "need to be blocked". Resulted in the cors error the question described.

Just disabling the adblocker did resolve the issue.

Shamus answered 3/2, 2022 at 15:25 Comment(0)
O
0

Had the same issue, and it was Firefox Focus extension (which have some content blockers) I earlier added in Safari iOS.

I suggest going to Settings > Safari > Extensions and try disabling extensions.

Overlay answered 20/8, 2022 at 22:18 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.