h345k34cr
h345k34cr

Reputation: 3480

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

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?

Upvotes: 33

Views: 90423

Answers (5)

Raziel
Raziel

Reputation: 21

solved this by replacing localhost with 127.0.0.1 everywhere

Upvotes: 2

Vukadin Nedeljkovic
Vukadin Nedeljkovic

Reputation: 1

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.

Upvotes: 0

Nitsan BenHanoch
Nitsan BenHanoch

Reputation: 689

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

Upvotes: 2

psimms
psimms

Reputation: 300

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.

Upvotes: 0

spiraleddy
spiraleddy

Reputation: 317

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]

Upvotes: 11

Related Questions