XMLHTTPRequest Not returning - javascript

I created a java script to connect to my web service however I never return from the send method of my request:
var request = new XMLHttpRequest();
request.overrideMimeType('text/plain');
request.open("GET", url, false);
request.send(null);
alert("Complete");
I never see the alert. However when I step through my service it returns successfully so it has to be with this script.
Note: I can run the url from a browser, chorme or firefox tested, and I am able to get the response I want. I just cannot get it from js.

My web service was not set up to receive HTTP GET request (REST based service). I was only set up to handle SOAP based requests.

Perhaps it is because of the false in request.open(), which means that the request is synchronous, so the rest of the script won't continue executing until the response has arrived from the server. Does the server return the response package? If it doesn't, you should try changing the third argument of the function to true, it should continue with the script execution then.
Check this link out: https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest#send()

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.

Why doesn't d3.json send cookies with the request?

I'm new to doing ajax requests with the built-in methods in d3.js (v5). Here's my code:
d3.json(uri).then(data =>console.log(data));
I tried this in an app that uses cookie authentication, and kept getting 401 status codes. Using the chrome dev tools revealed that it's sending the request without any cookies at all.
That's weird because ajax requests in native javascript send cookies along with every request by default. Here's an example of an ajax request in native javascript:
function nativeAjax(uri, callback) {
let request = new XMLHttpRequest();
request.onreadystatechange = function () {
if (request.readyState === 4) {
callback(request);
}
}
request.open('get', uri, true);
request.send(null);
}
nativeAjax(uri, request => console.log(request.status));
Plugging this into my app, chrome dev tools shows it does send the authentication cookie along with the request and indeed the request.status comes back as 200 showing that it is indeed authenticated.
My questions are:
how can I configure d3.json to send the required cookie?
how do I catch the response by status? I'm going to want to do something different for 401 response than 403 response, for example.
Where can I read a more complete documentation or examples for how to do use d3.json? I've always done native ajax because I don't use jquery, but if it's part of the library I'm using anyway, I'd like to learn how to use it. But the documentation says almost nothing about it, and the page it links to isn't helpful either. And most tutorials were for previous versions of d3 and don't work anymore.
Version 5 switched to use the Fetch API, which doesn't send any cookies by default. You can overcome this by adding options for d3.json to pass through to fetch:
d3.json(uri, {credentials: "same-origin"}).then(...);
Or, for cross-origin requests:
d3.json(uri, {credentials: "include"}).then(...);
If a 4XX status (or 5XX) is returned D3 will cause the promise to reject, which you can handle by providing a second callback function to then. I welcome corrections, but I believe there is no way within this function to get the actual status code.
The only mention of the change to Fetch and promises I found in the documentation (at the time of writing) was in the changelog: D3 v5 Changes.

spurious ajax OPTIONS request being made along with a GET request

I am making a standard ajax request with the code below
let x = new XMLHttpRequest();
x.onload = function(event) { …};
x.open("GET", url, true);
x.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
x.send();
The problem is that, for some reason I can't fathom, two ajax requests are made. The first one is an OPTIONS request and the second one is the GET request that I actually wanted. Any idea why?
My server is a nodejs app which I am starting using nodemon which restarts the server if it senses index.js has changed (this is helpful in development when you don't want to stop and restart the server). With this OPTIONS business, nodemon thinks my index.js has changed and restarts nodejs.
Additionally, the OPTIONS request results in a successful request that returns http 200. But, nothing is returned to the web page that initiated that ajax request in the first place (this could be that immediately after the OPTIONS request, nodejs is restarted by nodemon. Then the GET request is repeated, also with 200, and the web page gets the result
The problem is that, for some reason I can't fathom, two ajax requests are made. The first one is an OPTIONS request and the second one is the GET request that I actually wanted. Any idea why?
Because you're making a cross-origin call (for instance, from http://localhost to http://localhost:someport), which is normally disallowed by the Same Origin Policy. So the browser sends a "pre-flight" OPTIONS request to see if the server wants to allow the call via Cross-Origin Resource Sharing.

Auth differentiation between XHR and standard execute

I have the following method
private function adminRequired($accessControl)
{
$user = new \CloseCall\ValueObject\User(2);
if(!$accessControl->isAdmin($user)) {
header("location: /auth");
http_response_code(401);
}
}
Within my controller, this method is always ran as the controller is constructed to check whether a user has admin priveleges or not.
The issue I'm having with this is that XHR requests can also be sent to this controller and a header redirect is not suitable for this, in this case I would want to send a 401 http response back to the javascript and handle this response there.
If I send a header redirect then an http response code then the header redirect is skipped when executing the controller normally.
If I send the response code and then the header redirect then the javascript tries to XHR to my /auth controller.
My question is how can I either differentiate between an XHR request and a standard execute or better yet, handle this gracefully?
By default, there is no way to tell the difference.
Usually, you would add extra headers to the request. The most RESTful way to do that would be to use the Accept header.
e.g.
xhr.setRequestHeader("Accept", "application/json");
… to say that you prefer JSON as the response format.
The server can then test to see if JSON is prefered over HTML and then assume it wants an API style response (rather an HTML response).
A less RESTful and more hacky approach is to use a completely custom header:
xhr.setRequestHeader("x-requested-with", "xmlhttprequest");

What is 'xmlhttp.setRequestHeader();' and in which situations is it used?

I stumbled on this command while learning AJAX. The guy who made the tutorial didn't explain this command, what do the parameters inside the command mean and what is it used for... Below is the code I used it in:
<script type="text/javascript">
function insert(){
if(window.XMLHttpRequest){
xmlhttp = new XMLHttpRequest();
}else{
xmlhttp = new ActiveXObject('Microsoft.XMLHTTP');
};
xmlhttp.onreadystatechange = function(){
if(xmlhttp.readyState == 4 && xmlhttp.status == 200){
document.getElementById('message').innerHTML = xmlhttp.responseText;
};
};
parameters = 'insert_text='+document.getElementById('insert_text').value;
xmlhttp.open('POST','ajax_posting_data.php',true);
xmlhttp.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
xmlhttp.send(parameters);
};
</script>
HTTP is a protocol. Part of that protocol is the concept of request headers. When an xhr happens, text is exchanged between the client and server. Request headers are part of the text that the client sends to the server.
This is a way to set the request headers. The arguments you see are
1) the header to set (in this case, Content-type)
2) the header value. (in this case, x-www-form-urlencoded)
See this for more info.
HTTP requests are messages passed from one computer system to another according to a set routine (a 'protocol' - here HyperText Transfer Protocol) in order to do things like send data, ask for data to be sent back, update data previously sent, etc.
A header is basically a piece of information about the data in the body of the HTTP request. Its purpose is to tell the machine receiving the request what type of data is enclosed in the body of the request, its formatting, the language used, if it's to set a cookie, the date, the host machine, etc.
More than one header can be put on a HTTP request and each header has a 'name' and a 'value' component. On web pages they look like
<meta name="........" content="............."/>
and you find them just below the top of the web page within the element.
To enable people to send HTTP requests from within a JavaScript function, we create a new XMLHttpRequest object, just as your code does so with
const xmlhttp = new XMLHttpRequest();
To this new empty object you intend to add data. Despite its name, XMLHttpRequest also allows sending data in a number of formats other than XML, e.g. HTML code, text, JSON, etc. In your example each data name will be separated from its value by an "=" character and each data/value pairing will be separated from the next pairing by an "&" character. This kind of formatting is known as URL encoding.
We have to tell the receiving computer how the data within the HTTP request body is encoded. There is a standard header to convey this and it is added to the request via the method setRequestHeader(..). This method uses 2 parameters, the header name and the header's value. All this operation is achieved in the line
xmlhttp.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
This setRequestHeader(..) method must be applied to the request after the request is characterized with the open(...) method but before the final request is sent off with the send(.) method.
The open(...) method defines: (1) the type of HTTP request, e.g. GET/POST/PUT etc; (2) the web page that contains the handling script for this request, e.g. some .php file or Node.js request endpoint that makes the appropriate query to the back end database; and (3) the nature of the request dynamics, e.g. asynchronous requests are assigned a value 'true', synchronous requests are assigned 'false'.
The send(.) method attaches the data to be sent within the body of the request, in your case the variable called 'parameters'.
On your broader question of which situations setRequestHeader(..) is used, I would say that it is used in most HTTP request situations. But some types of data added to the body of a HTTP request invoke a default setting for the 'Content-Type' header.
It is exactly what it says. It will set a "header" information for the next XMLHttpRequest.
A header is pretty much a key/value pair. It is used to transmit "meta" information to the target server for the ongoing request. In your particular instance, its used to tell the server which content type is used for this request.
It sets the Content-type HTTP header to contain url encoded data sent from a form.

Categories

Resources