I'm getting this error using ngResource to call a REST API on Amazon Web Services:
XMLHttpRequest cannot load http://server.apiurl.com:8000/s/login?login=facebook. Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost' is therefore not allowed access. Error 405
Service:
socialMarkt.factory('loginService', ['$resource', function($resource){
var apiAddress = "http://server.apiurl.com:8000/s/login/";
return $resource(apiAddress, { login:"facebook", access_token: "@access_token" ,facebook_id: "@facebook_id" }, {
getUser: {method:'POST'}
});
}]);
Controller:
[...]
loginService.getUser(JSON.stringify(fbObj)),
function(data){
console.log(data);
},
function(result) {
console.error('Error', result.status);
}
[...]
I'm using Chrome, and I dont know what else to do in order to fix this problem. I've even configured the server to accept headers from origin localhost
.
Something that is very easy to miss...
IN solution explorer, right-click api-project. In properties window set 'Anonymous Authentication' to Enabled !!!
For those are using Lambda Integrated Proxy with API Gateway. You need configure your lambda function as if you are submitting your requests to it directly, meaning the function should set up the response headers properly. (If you are using custom lambda functions, this will be handled by the API Gateway.)
There are some caveats when it comes to CORS. First, it does not allow wildcards
*
but don't hold me on this one I've read it somewhere and I can't find the article now.If you are making requests from a different domain you need to add the allow origin headers.
Access-Control-Allow-Origin: www.other.com
If you are making requests that affect server resources like POST/PUT/PATCH, and if the mime type is different than the following
application/x-www-form-urlencoded
,multipart/form-data
, ortext/plain
the browser will automatically make a pre-flight OPTIONS request to check with the server if it would allow it.So your API/server needs to handle these OPTIONS requests accordingly, you need to respond with the appropriate
access control headers
and the http response status code needs to be200
.The headers should be something like this, adjust them for your needs:
Access-Control-Allow-Methods: GET, POST, PUT, PATCH, POST, DELETE, OPTIONS Access-Control-Allow-Headers: Content-Type Access-Control-Max-Age: 86400
The max-age header is important, in my case, it wouldn't work without it, I guess the browser needs the info for how long the "access rights" are valid.In addition, if you are making e.g. a
POST
request withapplication/json
mime from a different domain you also need to add the previously mentioned allow origin header, so it would look like this:Access-Control-Allow-Origin: www.other.com Access-Control-Allow-Methods: GET, POST, PUT, PATCH, POST, DELETE, OPTIONS Access-Control-Allow-Headers: Content-Type Access-Control-Max-Age: 86400
When the pre-flight succeeds and gets all the needed info your actual request will be made.
Generally speaking, whatever
Access-Control
headers are requested in the initial or pre-flight request, should be given in the response in order for it to work.There is a good example in the MDN docs here on this link, and you should also check out this SO post
A very common cause of this error could be that the host API had mapped the request to a http method (e.g. PUT) and the API client is calling the API using a different http method (e.g. POST or GET)
I have faced with this problem when DNS server was set to 8.8.8.8 (google's). Actually, the problem was in router, my application tried to connect with server through the google, not locally (for my particular case). I have removed 8.8.8.8 and this solved the issue. I know that this issues solved by CORS settings, but maybe someone will have the same trouble as me
If you're writing a chrome-extension
You have to add in the
manifest.json
the permissions for your domain(s).