I'm trying to send some HTTP requests from my angular.js application to my server, but I need to solve some CORS errors.
The HTTP request is made using the following code:
functions.test = function(foo, bar) {
return $http({
method: 'POST',
url: api_endpoint + 'test',
headers: {
'foo': 'value',
'content-type': 'application/json'
},
data: {
bar:'value'
}
});
};
The first try ended up with some CORS errors. So I've added the following lines to my PHP script:
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: POST, GET, OPTIONS, DELETE, PUT');
header('Access-Control-Allow-Headers: X-Requested-With, Content-Type, Origin, Authorization, Accept, Client-Security-Token, Accept-Encoding, X-Auth-Token, content-type');
The first error is now eliminated.
Now the Chrome's developer console shows me the following errors:
angular.js:12011 OPTIONS http://localhost:8000/test (anonymous function)
423ef03a:1 XMLHttpRequest cannot load http://localhost:8000/test. Response for preflight has invalid HTTP status code 400
and the network request looks like I expected (HTTP status 400
is also expected):
I can't imagine how to solve the thing (and how to understand) why the request will send on localhost as OPTIONS
and to remote servers as POST
. Is there a solution how to fix this strange issue?
In these situations, like when using custom headers, the browser is just checking with the server first that the server is willing to accept the request before sending it as sending unsolicited requests to the server could be really dangerous for your data, and also, what's the point in the browser sending potentially ...
Prevent sending the post data, if it wont be processed This is the only reason what is valid. Using options request will prevent sending the post data to the server unnecessarily.
This pre-flight request is made by some browsers as a safety measure to ensure that the request being done is trusted by the server. Meaning the server understands that the method, origin and headers being sent on the request are safe to act upon.
It is a bit awkward requirement since Angular is JavaScript framework and It does not accept post request because post request needs to be handled at server side only not at client side.
The OPTIONS
request is so called pre-flight request, which is part of Cross-origin resource sharing (CORS). Browsers use it to check if a request is allowed from a particular domain as follows:
POST
request with the application/json
content typeOPTIONS
request to the same URL2XX
status response, the browser won't send the actual request (because he knows now that it would be refused anyway)HTTP 200 OK
(or any other 2XX
) response, the browser will send the actual request, POST
in your caseSo, in your case, the proper header is present, you just have to make sure the pre-flight request's response HTTP status code is 200 OK
or some other successful one (2XX
).
Browsers are not sending the pre-flight requests in some cases, those are so-called simple requests and are used in the following conditions:
- One of the allowed methods: -
GET
-HEAD
-POST
Accept
Accept-Language
Content-Language
Content-Type
(but note the additional requirements below)DPR
Downlink
Save-Data
Viewport-Width
Width
application/x-www-form-urlencoded
multipart/form-data
text/plain
XMLHttpRequestUpload
object used in the request; these are accessed using the XMLHttpRequest.upload
property.ReadableStream
object is used in the request.Such requests are sent directly and the server simply successfully processes the request or replies with an error in case it didn't match the CORS rules. In any case, the response will contain the CORS headers Access-Control-Allow-*
.
Browsers are sending the pre-flight requests if the actual request doesn't meet the simple request conditions, the most usually:
application/xml
or application/json
, etc., are usedGET
, HEAD
or POST
POST
method is of an another content type than application/x-www-form-urlencoded
, multipart/form-data
or text/plain
You need to make sure that the response to the pre-flight request has the following attributes:
200 OK
Access-Control-Allow-Origin: *
(a wildcard *
allows a request from any domain, you can use any specific domain to restrict the access here of course)From the other side, the server may refuse the CORS request simply by sending a response to the pre-flight request with the following attributes:
2XX
)200 OK
), but without any CORS header (i.e. Access-Control-Allow-*
)See the documentation on Mozilla Developer Network or for example HTML5Rocks' CORS tutorial for details.
I ran into a very similar problem writing an Angular 2 app - that uses a NODE server for the API.
Since I am developing on my local machine, I kept getting Cross Origin Header problems, when I would try to POST to the API from my Angular app.
Setting the Headers (in the node server) as below worked for GET requests, but my PUT requests kept posting empty objects to the database.
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: POST, GET, OPTIONS, DELETE, PUT');
header('Access-Control-Allow-Headers: X-Requested-With, Content-Type,
Origin, Authorization, Accept, Client-Security-Token, Accept-
Encoding, X-Auth-Token, content-type');
After reading Dawid Ferenczy's post, I realized that the PREFLIGHT request was sending blank data to my server, and that's why my DB entries were empty, so I added this line in the NODE JS server:
if (req.method == "OPTIONS")
{
res.writeHead(200, {"Content-Type": "application/json"});
res.end();
}
So now my server ignores the PREFLIGHT request, (and returns status 200, to let the browser know everything is groovy...) and that way, the real request can go through and I get real data posted to my DB!
Just put
if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS') {
header("HTTP/1.1 200 ");
exit;}
at the beginning of your serverside app and you should be fine.
For spring boot application, to enable cors request, use @CrossOrigin(origins = "*", maxAge = 3600)
on your respective controller.
Refer this doc
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With