I've got a simple code that sends files to server from https://app.myserver:4202 to https://myserver/backend/upload.php:
//script executed on`https://app.myserver:4202`
var xhr = new XMLHttpRequest();
xhr.open("POST", "https://myserver.com/backend/upload.php");
xhr.withCredentials = true;
xhr.send(fd); //fd is formdata from file input
yay, it successfully sends the files with cookie so I can perform user authentication in my upload.php script. Now, I also want to display progress bar so I changed the code to this:
var xhr = new XMLHttpRequest();
xhr.open("POST", "https://myserver.com/backend/upload.php");
xhr.withCredentials = true;
xhr.upload.addEventListener("progress", function(evt){
if (evt.lengthComputable) {
console.log("add upload event-listener" + evt.loaded + "/" + evt.total);
}
}, true);
xhr.send(fd);
Whoa, all hell broke loose! We have a CORS problem. Notice that I only added a progress tracker.
Access to XMLHttpRequest at 'https://myserver/backend/upload.php' from origin 'https://myserver:4202' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: It does not have HTTP ok status.
I took great care to setup CORS correctly so this are myserver response headers that are relevant to CORS
Access-Control-Allow-Credentials: true
Access-Control-Allow-Headers: origin, x-requested-with, content-type
Access-Control-Allow-Methods: DELETE, HEAD, GET, OPTIONS, POST, PUT
Access-Control-Allow-Origin: https://app.myserver.com:4202
Access-Control-Max-Age: 86400
They work well, if no progress info is desired, but fail when it is tracked.
So tell me, what am I missing out here?
We have a CORS problem. Notice that I only added a progress tracker.
This behaviour is defined in the spec:
Registering one or more event listeners on an XMLHttpRequestUpload object will result in a CORS-preflight request. (That is because registering an event listener causes the upload listener flag to be set, which in turn causes the use-CORS-preflight flag to be set.)
I took great care to setup CORS correctly so this are myserver response headers that are relevant to CORS
Read the error message carefully:
Access to XMLHttpRequest at 'https://myserver/backend/upload.php' from origin 'https://myserver:4202' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: It does not have HTTP ok status.
So the HTTP response headers you set aren't really relevant.
The browser is making the OPTIONS request to ask for permission to make the POST request and the server is responding with something other that 200 OK.
Possibly it is sending 405 Method Not Allowed. Check the Network tab of your developer tools to find out exactly what the HTTP response status is, and then adjust the server accordingly.
Related
From: https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#preflighted_requests
The following is an example of a request that will be preflighted:
const xhr = new XMLHttpRequest();
xhr.open('POST', 'https://bar.other/resources/post-here/');
xhr.setRequestHeader('X-PINGOTHER', 'pingpong');
xhr.setRequestHeader('Content-Type', 'application/xml');
xhr.onreadystatechange = handler;
xhr.send('<person><name>Arun</name></person>');
The example above creates an XML body to send with the POST request.
Also, a non-standard HTTP X-PINGOTHER request header is set. Such
headers are not part of HTTP/1.1, but are generally useful to web
applications. Since the request uses a Content-Type of
application/xml, and since a custom header is set, this request is
preflighted.
Will a preflight request be triggered if the request is same-origin but does not follow the header guidelines?
No, preflight requests are only done for cross-site requests. If you look at the beginning of the MDN article there is an image that explicitly says "Same origin-requets (always allowed)" as an example.
The below image isn't very visible if running SO in dark mode, if so, check the image in the article on the url below.
https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS
I am using the Pons dictionary API documented here: https://en.pons.com/assets/docs/api_dict.pdf
It works when I use a get request in my mac terminal, but not when using XMLHttpRequest in my javascript file (shown below) when testing it in my browser. It always gives me a 404 error and then states
"Access to XMLHttpRequest at 'https://api.pons.com/v1/dictionary?q=casa&l=dees' from origin 'null' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: It does not have HTTP ok status."
Any ideas?
I have tried making a request that does not require my X-Secret (credentials) and it works, but as soon as I set the X-Secret header it throws a 404 error. I need to set this heading for most request types.
Here is my code. I have censored my credentials in the X-Secret header.
var request = new XMLHttpRequest()
let url = new URL('https://api.pons.com/v1/dictionary');
url.searchParams.set('q', 'casa');
url.searchParams.set('l', 'dees');
request.open('GET', url);
//request.withCredentials = true;
request.setRequestHeader("X-Secret", "***");
request.setRequestHeader("Access-Control-Allow-Origin", "*");
request.setRequestHeader("Access-Control-Allow-Credentials", "true");
request.setRequestHeader("Access-Control-Allow-Methods", "GET,HEAD,OPTIONS,POST,PUT");
request.setRequestHeader("Access-Control-Allow-Headers", "Access-Control-Allow-Headers, Origin, Accept, X-Requested-With, Content-Type, Access-Control-Request-Method, Access-Control-Request-Headers, Authorization");
request.send()
request.onload = function() {
// Begin accessing JSON data here
var data = JSON.parse(this.response)
if (request.status >= 200 && request.status < 400) {
console.log(data)
} else {
console.log('error')
}
}
CORS is "cross-origin resource sharing"; specifically, it's used to refer to policies that block requests between different domains. In this case, XHR is sending a "preflight request" -- that is, a request with verb OPTIONS (rather than GET, POST, etc.) -- to make sure the server will accept a real request. It will do this whenever you use non-standard (and some standard but optional) headers. The preflight request is coming back as 404; the server doesn't support OPTIONS to that endpoint.
The way to get around CORS is to use a proxy. That is, have a backend script (in Node, PHP, whatever) on your domain that sends the request to the other API server and echoes its response. CORS only applies to AJAX requests, not backend ones, so this will get around the issue, and it is the accepted technique.
I've been working with CORS and encountered the following issue.
Client complains about no 'Access-Control-Allow-Origin' header is present, while they are present, and client make the actual POST request and receives 200.
function initializeXMLHttpRequest(url) { //the code that initialize the xhr
var xhr = new XMLHttpRequest();
xhr.open('POST', url, true);
xhr.withCredentials = true;
xhr.setRequestHeader('Content-Type', 'application/json; charset=UTF-8');
//set headers
for (var key in headers) {
if (headers.hasOwnProperty(key)) { //filter out inherited properties
xhr.setRequestHeader(key,headers[key]);
}
}
return xhr;
}
In Chrome
chrome console log
Chrome OPTIONS request
Chrome POST request
In Firefox
Firefox Console Log
Firefox OPTIONS request
Firefox POST request
In short: Access control headers (e.g. Access-Control-Allow-Origin) need to present in response for both OPTIONS and actual POST.
Work Flow:
Client make OPTIONS request with those HTTP access headers. (e.g. Origin, Access-Control-Request-Method, Access-Control-Request-Headers)
Server respond with those access control headers, allowing access. (e.g. Access-Control-Allow-Origin, Access-Control-Expose-Headers, Access-Control-Max-Age, Access-Control-Allow-Credentials, Access-Control-Allow-Methods, Access-Control-Allow-Headers)
Client makes POST request with data.
Server respond to POST. If Access-Control-Allow-Origin header is NOT present in the server response. Although the POST is successful and shows 200 status code in network tab, xhr.status is 0 and xhr.onerror will be triggered. And browser would show up the error message.
Header References:
https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS
Value null for Access-Control-Allow-Origin won't do, it has to be either the origin domain or * to allow any origin.
For more details, refer to MDN.
I am trying to create a javascript+html which actually performs the action like CSRF (Cross site request forgery). So far, I am able to do this.
<html> <head>
<script type="text/javascript">
function logData() {
var xhr = new XMLHttpRequest()
xhr.open("POST", "https://example.com", true);
xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
xhr.setRequestHeader("Accept-Language", "en-US,en;q=0.5");
xhr.setRequestHeader("Accept", "application/json, text/javascript, */*; q=0.01");
xhr.send("data"); } </script> </head> <body>
<input type="submit" value="Submit request" onclick="logData()" /> </body> </html>
When I am running this, I got the error like shown below:
"XMLHttpRequest cannot load https://example.com. Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'null' is therefore not allowed access. The response had HTTP status code 400."
After a bit googling I came to know that this error s producing because of this reason:
". The reason is that there is what's called a preflight request before the actual request, which is an OPTIONS request. So the error comes from the fact that the preflight request doesn't produce the necessary headers"
SO, I have tried to add CORSFilter on the same code shown above. Honestly speaking, I don't have much good hands on javascript.
So, please let me know...how to add CORSfilter here..
Thanks very much
It is the server that needs to include the Access-Control-Allow-Origin header in the response. Your server needs to include something like Access-Control-Allow-Origin: https://example.com.
It's possible your request is making a "preflight" OPTIONS request to the server to ask about CORS capabilities. Not only should your POST request handler send the Access-Control-Allow-Origin: * header along with the response, but you should create an OPTIONS request handler that sends this header as well. There is more information in this MDN documentation about the preflight OPTIONS request. You should be able to look in your inspector to see if the browser is making this preflight request or not. When I build the OPTIONS request handler, I usually respond with these headers (which can also be found in the MDN documentation I linked):
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: POST, GET, OPTIONS
Access-Control-Max-Age: 1728000
I'm struggling for quite some time already with issuing a simple GET request to a 3rd party REST Api. I've read a bit of tutorials and SO questions but I just can't get it to work. I am getting one of two errors
Response for preflight is invalid (redirect)
or (if via https)
Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'https://localhost:8433' is therefore not allowed access.
About 2nd message: Is it just a problem with the server not supporting CORS?
My code:
var xmlHttp = new XMLHttpRequest();
var url = 'https://inspirehep.net/record/451647?of=recjson&ot=recid,number_of_citations,authors,title'; //http or https, tried both
/*
doing sth with response here like populate dropdown etc.
*/
xmlHttp.open('GET', url, true);
xmlHttp.setRequestHeader("Access-Control-Allow-Headers", "Content-Type, X-Requested-With, Cache-Control");
xmlHttp.setRequestHeader("Content-Type", "application/json");
xmlHttp.setRequestHeader("Access-Control-Allow-Origin", '*');
xmlHttp.setRequestHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
xmlHttp.setRequestHeader("Access-Control-Allow-Credentials", "true");
xmlHttp.send();
Whole app is running on node.js server (localhost) and the script above is included as separate file in .html view.
I can correctly get json response from web-browser, fiddler, postman etc. for this API. I also tried different APIs (e.g. Openweather API) thinking that it's the problem with server configuration, but the result was the same.
I would be thankful for any help - maybe i'm just misunderstanding something about CORS.
you cannot set headers from the browser, if the target url runs on your server or a server that you manage and that server runs nodejs you can use cors https://www.npmjs.com/package/cors, however, if this is a third party url and it doesn't not allow CORS, then you should make the request from the your back-end through configuring a proxy from your server to third party server, that should resolve your problem.
The answer on CORS with nodejs is most likely right, but I want to suggest that you run a test to make sure your code works fine as well.
Try with Chrome and download an extension to allow CORS. This way you will test the functionality first before trying the right solution.
Late to the party...
http://cors-anywhere.herokuapp.com/ is great, but you don't need it if you are using XMLHttpRequest() and a GET method. Simply exclude your header requests...
var xhr = new XMLHttpRequest();
xhr.open( "GET", YOURURL );
//OMIT THESE...
//xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
//xhr.withCredentials = true;
//xhr.setRequestHeader( 'Content-Type', _contenttype );
//xhr.setRequestHeader( 'CrossDomain', 'true' );
//....
xhr.addEventListener( 'load', function () {
xhr.responseJSON = JSON.parse( xhr.responseText );
alert( xhr.responseJSON);
});
xhr.onerror = function(e) {
alert("Ajax request error");
};
xhr.send( JSON.stringify({}) );