Reputation: 3480
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
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
Reputation: 689
In my case, I was using http
instead of https
,
Which made Safari not include my Authorization
header.
Upvotes: 2
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
Reputation: 317
My suggestion, if you have control of your server is to add a terminating forward slash on your 'http://localhost:8888/myPath/'.
const res = await fetch('http://localhost:8888/myPath/', {
method: 'POST',
mode: 'cors',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(body)
});
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.
Upvotes: 11