Targetting HTTP Error Messages - javascript

I'm trying to send an JSON-encoded data string to a remote machine using AJAX.
Whenever I try to send the data string to the remote machine, one of two error messages will occur:
XMLHttpRequest cannot load http://10.1.0.139:8000/.
No 'Access-Control-Allow-Origin' header is present on
the requested resource. Origin 'http://localhost' is
therefore not allowed access.
This message occurs when the remote machine is powered on and accepting connections. However, although I am getting this error, my code is working exactly as I want it to - as in, the remote machine receives the correct piece of data.
POST http://10.1.0.139:8000/ net::ERR_CONNECTION_REFUSED
And this message occurs when the remote machine is either powered off or does not have it's own server running that accepts incoming requests and connections.
The problem is, I want to be able to differentiate between these two error messages, and I do not know how. I can't use AJAX callbacks such as error() or fail(), because there will always be an error - and it will say that there has been a failed request despite a HTTP status of 200 suggesting that everything is okay (when the first error message shows).
Is there a way that I can do something similar to a Pseudo command of 'IF I FAIL TO CONNECT TO REMOTE MACHINE, DO...'
EDIT
Something I've noticed just now is that my remote machine does not display incoming connections from Internet Explorer - instead it displays this:
XMLHttpRequest: Network Error 0x2efd,
Could not complete the operation due to error 00002efd.

Use the XMLHttpRequest timeout
var xhr = new window.XMLHttpRequest();
var data = 'x=1';
xhr.open('POST', 'http://10.1.0.139:8000/');
xhr.timeout = 5000;
xhr.addEventListener('timeout', function(e) {
// handle dead server
console.log('timeout');
console.error(e);
});
xhr.addEventListener('error', function(e) {
// handle error - CORS probably in this case
console.log('error');
console.error(e);
});
xhr.addEventListener('load', function(e) {
// handle success
console.log('load');
console.info(e);
});
xhr.send(data);
This triggers error in the case of a CORS error, and timeout in the case of no server

Related

XMLHttpRequest causes two network events

I'm noticing when I have use a XMLHttpRequest in my script, that for each time it gets called two events appear in Chrome's network waterfall.
The first event has a type xhr and a size of around ~27bytes and the second event has a type of text/html and a size of 0bytes.
I've noticed it in the past and have looked over it, but now I'm noticing its causing the page it connects to for it to run twice.
Is this normal? Did I implement something incorrectly?
function example(){
console.log('ran'); // this shows the function only ran once
var form = new FormData(), xml = new XMLHttpRequest();
form.append('test', '...');
xml.upload.onprogress = function(e){something.style.width = (e.loaded*100/e.total) + "%";}
xml.onload = function(){alert('done');}
xml.open('POST', 'https://externaldomainexample.net', true);
xml.send(form);
}
The two requests are being made because you are making a request to a different domain from which your page is hosted (cross origin). If you enable the "method" column in Chrome's network tab you'll see that the first request is an OPTIONS request, whereas the second is your POST request.
The first request is what's known as a Preflight request and asks the remote server what remote hosts are allowed to connect and what methods they are allowed to call. If this step fails, then you'll see an error in the browser saying the request has been "blocked by CORS policy".
If the preflight request is successful, then the second (POST) request is made.
Depending on how the server is configured, you may need to have it handle OPTIONS requests differently, so that it doesn't perform the same action twice.

NodeJS server - client behaves differently for response status 500, depending on response body

I have set up a NodeJS server, listening on localhost:3000, and I am testing it with Chrome browser.
When the response status code is 500:
If the response body is empty, then the client shows:
This page isn’t working
localhost is currently unable to handle this request.
HTTP ERROR 500
If the response body is not empty, then the client (surprisingly) shows it with no error
Here is a sample code to reproduce this:
let http = require("http");
let state = true;
let server = http.createServer(async function(request, response) {
if (request.url == "/") {
response.statusCode = 500;
response.end(state ? "" : "data");
console.log(state);
state = !state;
}
});
server.listen(3000, async function(error) {
if (error)
return console.log(error);
console.log("server is listening");
});
To tell you the truth, I am not worried about how the browser displays it, because my real client is some other process in the system. But I want to make sure that this process receives the correct status code (500) even if I enclose some data in the response body.
So I'd like to know if there is something wrong in my code (i.e., if I am not allowed to send data along with status 500), or if it's just Chrome's default behavior.
According to this post and this discussion Chrome if displaying a "friendly" error page is server responded with error code without the body (earlier it was for less than 512 bytes in response) - that's why you see a different behavior.
In most cases you would send the custom error page along with the error code, to display it to user. So there's no need to show error if there's a custom page displaying it anyway.
And if you just need to validate the response headers there are special extensions to chrome that allows you to see it. For example there's HTTP Headers.
Also I suppose you could use some kind of debugging proxy, like for example fiddler to capture the traffic, and inspect the requests and responses.

getting status code from resource with No 'Access-Control-Allow-Origin' header present

I'm using good 'ol XMLHttpRequest to make a GET request to https://www.instagram.com/USERNAME. My goal is to confirm that a the instagram username entered by my user actually exists, and it would be great if I could confirm this on the client side.
For instance, try to make a GET request to https://www.instagram.com/9gag and you get a 200 back. https://www.instagram.com/sakjafkhdsafd and you get a 404 back.
Now, now... seems like Instagram does not allow CORS... because when I run XMLHttpRequest.send() I get the following error:
XMLHttpRequest cannot load https://www.instagram.com/. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8080' is therefore not allowed access.
Ok, guess the server is going to have to take care of this... BUT! if I check my network tab, I actually see that the request is being made and I am getting a response back with the expected status code. I also get all the html, everything. What the...?
How is it that the browser (chrome in my case) is able to capture this but not my application?
Adding my code as requested:
var xhr = new XMLHttpRequest();
xhr.open("GET", "https://www.instagram.com/" + username, false);
xhr.onreadystatechange = function () {
if (xhr.readyState == 4 && xhr.status == 200) {
// do something...
}
}
xhr.send()
EDIT:
I just tested this on Firefox and I get a 301 back. I guess my question now is "what is chrome doing to get the expected status code on the network tab?"
Although the browser has successfully retrieved content, it is forbidding you to read any of it due to CORS.
CORS is a little confusing in itself - if the server was okay fulfilling the request, why does the browser block it? But okay, that's a security restriction that was pasted on in a backward-compatible way.
What is more surprising is that this is true even for errors: the server must add a special header to its response even to allow the client to read a status code or error message!
But the browser will display those in the browser console and network tab.

Why does my XMLHttpRequest have readystate 4 but status 0?

I have a content script in my Chrome extension which runs on some HTTPS page. It is trying to send a POST request to an HTTP page (by means of a background script) which is a route for an API that I have set up. I am trying to send JSON data over. However I am getting status 0, even though the ready state is 4. I used Postman to perform the same post and it worked. This leads me to believe it is a HTTPS protocol issue, however I am performing a GET on an HTTP page in the same background script and that is working fine. What might be the issue then? Here is my POST code:
var string = json;
xhr = new XMLHttpRequest();
xhr.open("POST", url, true);
xhr.setRequestHeader("Content-Type", "application/json");
xhr.onreadystatechange = function () {
if (xhr.readyState == 4 && xhr.status == 200) {
var json = JSON.parse(xhr.responseText);
}
};
xhr.send(string);
Thanks!
UPDATE:
I used the chrome developer tools to debug the background script and I found the error, which was "Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.". I guess background script errors do not print to the main console.
UPDATE:
I had to add the site I was posting to to the permissions field in my manifest. It works now.
I have a similar issue and, after debugging it for days, the only solution I found was to make the XMLHttpRequest synchronous by setting set the async param in the XMLHttpRequest open method to false.
The readyState value of 4 means the operation completed successfully or failed. The status property is initialized to 0 and will remain at 0 if an error occurs. Assign an event handler to the xhr.onerror property and I bet you'll see that handler fire. Unfortunately, the error event doesn't give any useful information about what caused the error.
To find out what caused the error, I would use the debug tools found in Chrome. Menu => More tools => Developer Tools. Then go to the "Network" tab. There you can see all the HTTP requests your webpage has made. It will show better details on any errors there.
What did you do?
I had to add the site I was posting to the permissions field in my manifest. It works now.
XMLHttpRequest.setRequestHeader("Access-Control-Allow-Origin", "the api website"); ?

How to check for No 'Access-Control-Allow-Origin' header error

When using XMLHttpRequest in JavaScript, is it possible to distinguish between the following two errors (GET completely failed / No 'Access-Control-Allow-Origin' header)?
Obviously, readyState and status of the XMLHttpRequest object don't differ. I tried to use window.onerror to catch all errors but apparently, these two errors do not trigger the callback function.
Your best course of action would be to prevent this error from even occurring in the first place. By making sure the server adds the domain you're trying to access from your script to the Access-Control-Allow-Origin setting you don't have to deal with it client-side.
That said, you should be able to attach a handler to the error event of the XMLHttpRequest object. Using the error message you might be able determine what went wrong; but that is of lesser interest. It doesn't matter to the client what went wrong, only that it isn't going to get it's data, so you can plan accordingly.
var oReq = new XMLHttpRequest();
oReq.addEventListener("error", transferFailed);
oReq.open();
function transferFailed(evt) {
console.log("An error occurred while transferring the file.");
}
More information: https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/Using_XMLHttpRequest#Asynchronous_request

Categories

Resources