Your server's response allows the request to include three specific non-simple headers:
Access-Control-Allow-Headers:origin, x-requested-with, content-type
but your request has a header not allowed by the server's response:
Access-Control-Request-Headers:access-control-allow-origin, content-type
All non-simple headers sent in a CORS request must be explicitly allowed by the Access-Control-Allow-Headers
response header. The unnecessary Access-Control-Allow-Origin
header sent in your request is not allowed by the server's CORS response. This is exactly what the "...not allowed by Access-Control-Allow-Headers
" error message was trying to tell you.
There is no reason for the request to have this header: it does nothing, because Access-Control-Allow-Origin
is a response header, not a request header.
Solution: Remove the setRequestHeader
call that adds a Access-Control-Allow-Origin
header to your request.
This is by design. You can't make an arbitrary HTTP request to another server using XMLHttpRequest unless that server allows it by putting out an Access-Control-Allow-Origin header for the requesting host.
https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS
You could retrieve it in a script tag (there isn't the same restriction on scripts and images and stylesheets), but unless the content returned is a script, it won't do you much good.
Here's a tutorial on CORS:
http://www.bennadel.com/blog/2327-cross-origin-resource-sharing-cors-ajax-requests-between-jquery-and-node-js.htm
This is all done to protect the end user. Assuming that an image is actually an image, a stylesheet is just a stylesheet and a script is just a script, requesting those resources from another server can't really do any harm.
But in general, cross-origin requests can do really bad things. Say that you, Zoltan, are using coolsharks.com. Say also that you are logged into mybank.com and there is a cookie for mybank.com in your browser. Now, suppose that coolsharks.com sends an AJAX request to mybank.com, asking to transfer all your money into another account. Because you have a mybank.com cookie stored, they successfully complete the request. And all of this happens without your knowledge, because no page reload occurred. This is the danger of allowing general cross-site AJAX requests.
If you want to perform cross-site requests, you have two options:
- Get the server you are making the request to to either
a. Admit you by putting out a Access-Control-Allow-Origin header that includes you (or *)
b. Provide you with a JSONP API.
or
- Write your own browser that doesn't follow the standards and has no restrictions.
In (1), you must have the cooperation of the server you are making requests to, and in (2), you must have control over the end user's browser. If you can't fulfill (1) or (2), you're pretty much out of luck.
However, there is a third option (pointed out by charlietfl). You can make the request from a server that you do control and then pass the result back to your page. E.g.
<script>
$.ajax({
type: 'GET',
url: '/proxyAjax.php?url=http%3A%2F%2Fstackoverflow.com%2F10m',
dataType: 'text/html',
success: function() { alert("Success"); },
error: function() { alert("Error"); }
});
</script>
And then on your server, at its most simple:
<?php
// proxyAjax.php
// ... validation of params
// and checking of url against whitelist would happen here ...
// assume that $url now contains "http://stackoverflow.com/10m"
echo file_get_contents($url);
Of course, this method may run into other issues:
- Does the site you are a proxy for require the correct referrer or a certain IP address?
- Do cookies need to be passed through to the target server?
- Does your whitelist sufficiently protect you from making arbitrary requests?
- Which headers (e.g. modify time, etc) will you be passing back to the browser as your server received them and which ones will you omit or change?
- Will your server be implicated as having made a request that was unlawful (since you are acting as a proxy)?
I'm sure there are others. But if none of those issues prevent it, this third method could work quite well.
Best Answer
I wrote an article on this issue a while back, Cross Domain AJAX.
The easiest way to handle this if you have control of the responding server is to add a response header for:
This will allow cross-domain Ajax. In PHP, you'll want to modify the response like so:
You can just put the
Header set Access-Control-Allow-Origin *
setting in the Apache configuration or htaccess file.It should be noted that this effectively disables CORS protection, which very likely exposes your users to attack. If you don't know that you specifically need to use a wildcard, you should not use it, and instead you should whitelist your specific domain: