CORS request not working in Safari
JavascriptSafariXmlhttprequestCorsJavascript Problem Overview
I am making a CORS xhr request. This works fine in chrome, however when I run in safari I get an 'Can not load ---- access not allowed by Access-control-allow-origin'. The code is exactly the same and I have set the CORS on the server. Below is my code.(has access control, but you are free to try without the accessToken)
var water;
var req = new XMLHttpRequest;
req.overrideMimeType("application/json");
req.open('GET', 'https://storage.googleapis.com/fflog/135172watersupplies_json', true);
req.setRequestHeader('Authorization', 'Bearer ' + accessToken);
origThis = this;
var target = this;
req.onload = function() {
water = req;
req.send(null);
After looking at the request headers I see that a OPTIONS request is made first and this is the request that is not allowed. The origin header is not included in the response in Safari, but is in chrome. What would cause this. Any help would be greatly appreciated.
UPDATE: I have tried in Safari for Windows and it works, so I'm not sure what is going on here. The mac that I am using is a remote access (Macincloud.com), but I don't think that would have anything to do with it.
Javascript Solutions
Solution 1 - Javascript
I encountered the same error when making an XHR request against a file in Amazon S3. On Safari 7 it was failing. I know you're not using Amazon S3, but I thought I'd post in case this solution helped others.
The problem was that Safari 7 set the Access-Control-Request-Headers header to "origin, x-requested-with", but my AWS CORS configuration only allowed "x-requested-with":
<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
<CORSRule>
<AllowedOrigin>*</AllowedOrigin>
<AllowedMethod>GET</AllowedMethod>
<MaxAgeSeconds>3000</MaxAgeSeconds>
<AllowedHeader>Authorization</AllowedHeader>
<AllowedHeader>x-requested-with</AllowedHeader>
</CORSRule>
</CORSConfiguration>
I added "origin" as an allowed header and everything worked fine.
<AllowedHeader>origin</AllowedHeader>
Note: the AllowedOrigin of *
is for development purposes only. See @andes comment below for more information.
Solution 2 - Javascript
I just had a similar problem, CORS error. It would work in Firefox & Chrome but not Safari 10.
Turned out we needed to put the trailing slash on the JSON URL.
Solution 3 - Javascript
As for Amazon S3, it only worked in safari after I added more allowed headers, Content-Type and Range. One of these did the job.
<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
<CORSRule>
<AllowedOrigin>*</AllowedOrigin>
<AllowedMethod>GET</AllowedMethod>
<AllowedMethod>POST</AllowedMethod>
<MaxAgeSeconds>3000</MaxAgeSeconds>
<AllowedHeader>Authorization</AllowedHeader>
<AllowedHeader>Origin</AllowedHeader>
<AllowedHeader>X-Requested-With</AllowedHeader>
<AllowedHeader>Content-Type</AllowedHeader>
<AllowedHeader>Range</AllowedHeader>
</CORSRule>
</CORSConfiguration>
Solution 4 - Javascript
In my case, it was an issue for Accept-Language header. I have added Accept-Language
inside Access-Control-Allow-Headers
and it got resolved.
Solution 5 - Javascript
Im not sure if anyone else will have this problem but I was making a request to a URL like:
https://api.website.com/api/v1/users/auth0|5ef7502019360a7/
The |
(pipe) character in the URL was causing a strange issue with Safari because it was not being URL Encoded correctly.
In my Javascript I simply replaced my old url:
const url = "https://api.website.com/api/v1/user/auth0|5ef27593603a7";
with
const url = "https://api.website.com/api/v1/user/auth0|5ef27593603a7".replace("|", "%7C");
%7C
is the correct URL encoding for the |
(pipe) character.
Hope this helps someone!
Solution 6 - Javascript
Set two response headers:
-
Access-Control-Allow-Methods: '*', allow all
-
Turns out server had Access-Control-Allow-Methods response header's value is set to *. It had to explicitly set to allow methods instead of a wildcard as it is not supported by a safari in iOS as given here in this MDN doc.
https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Methods
Solution 7 - Javascript
For CORS request you should be using your origin fflog.storage.googleapis.com
. If you use common storage.googleapis.com
origin, any site can access to your bucket.
have try try remove overrideMimeType
? If you set mime type, it will return correctly.
I also have problem with Safari POST request, but no answer yet. GET is OK.
Solution 8 - Javascript
When I try
curl -v -X OPTIONS \
-H 'Origin: fflog.storage.googleapis.com' \
-H 'Access-Control-Request-Method: GET' \
https://storage.googleapis.com/fflog/135172watersupplies_json
I get, among other headers:
Access-Control-Allow-Origin: *
When I execute AJAX requests against https://storage.googleapis.com/fflog/135172watersupplies_json
from Safari 6.0.4 on Mac OS 10.8.3 I get 403 errors, but they do all execute.
So I can only guess that you are trying to send a credentialed request for which a wildcard Access-Control-Allow-Origin
is not allowed.
Solution 9 - Javascript
I had the same problem where CORS worked in Chrome, but threw an origin error in Safari. Turned out it was a Kerberos authorization issue. When I loaded the XHR URL directly in Safari, I was prompted for credentials. After entering them, I returned to the original site, and Safari no longer had the CORS error.
Solution 10 - Javascript
We had the exact same issue on Cloudfront
(backed by s3 bucket) and the solutions given here did not help. The problem was with Cloudfront clipping some headers. This resolved it for us:
https://aws.amazon.com/premiumsupport/knowledge-center/no-access-control-allow-origin-error/
Putting it here just in case someone comes across this solution in future.
Solution 11 - Javascript
I had a similar problem. I had a site where the login worked from site A, upon a successful login, the user would get redirected to site B. Both site A and B load the same language file from site A. What was happening to me, was that the file got first loaded on site A (No CORS required) but when the user went to site B, Safari interpreted it had that file already, but the internal failed with a CORS error, as it had it cached from site A.
The solution is to make the server add a "Vary: Origin" header to the response so that dumb Safari knows how to properly manage the cached file.
Solution 12 - Javascript
try to remove overide mimetype.
var
jsonhandler=function(){var req=JSON.parse(this.response);console.log(req)},
req=new XMLHttpRequest;
req.open('GET','https://storage.googleapis.com/fflog/135172watersupplies_json');
req.setRequestHeader('Authorization','Bearer '+accessToken);
req.onload=jsonhandler;
req.send();
Solution 13 - Javascript
Thanks for all the responses, I got this finally myself. I added 'Origin' to my responseHeaders and works fine now.