Is it possible to get only response headers from XMLHttpRequest without downloading file data?
If the server you are making the request to supports the method, it sounds like what you want is to make an HTTP HEAD request. See the HTTP spec.
For example compare the output from curl -v -X GET https://github.com and curl -v -X HEAD https://github.com.
Also see HTTP HEAD Request in Javascript/Ajax?
Using JavaScript (as specified in the question) simply use a head request via AJAX:
var xhr = new XMLHttpRequest();
var method = 'head';
var url = 'https://www.example.com/';
xhr.open(method,url,true);
xhr.send(null);
xhr.onreadystatechange = function()
{
if (xhr.readyState === 4)
{
console.log(xhr.getAllResponseHeaders())
}
}
Firstly, the answer from John fixes this issue but it got downvoted because it didn't have enough of an explanation.
So here is the fix with an explanation as well as an extra bit that you can add as well.
Client side solution is as follows (I am using the status code as the example):
function checkStatus(url) {
return new Promise((resolve, reject) => {
const request = new XMLHttpRequest();
request.open('HEAD', url, true)
request.onreadystatechange = () => {
if (request.readyState >= 2) {
resolve(request.status)
request.abort()
}
}
request.onerror = (e) => {
reject(e)
}
request.send()
})
}
The reason why this works is for two reasons.
Firstly we are passing HEAD in as the method instead of GET this should be enough on its own, but if you want to do more, you can move onto the second reason.
The second reason this works is because of the readyState states.
0 = UNSENT
1 = OPENED
2 = HEADERS_RECEIVED
3 = LOADING
4 = DONE
At state 2 the headers are ready to be viewed. This means you can then return whatever you need and/or abort the rest of the request preventing any further data being downloaded.
Worth noting you can also do this with request.onprogress at stage 3.
See https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/readyState and https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods for more details.
Related
I have been googling for hours now. I've read a dozen "answers" on Stackoverflow, all of them using jQuery.
This is the common answer...
The ajax-request will follow that redirect afaik
Well, it doesn't.
I am trying to send a PUT from a form via native JS AJAX
[Please I beg you, don't tell me to use jQuery. I found a bug in jQuery via PUT
(1) so I'm going around it]
This is my code snippet...
var xhr = new XMLHttpRequest();
xhr.open(method, url);
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.send(data);
xhr.onload = function (e) {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
console.log(xhr.responseText);
} else {
console.error(xhr.statusText);
}
}
};
xhr.onerror = function (e) {
console.error(xhr.statusText);
};
This block works great, I can POST, PUT and DELETE without issues. The server receives the data and updates the DB according to the sent METHOD just fine.
My (SLIM based) PHP, upon successful completion, returns a 302 and a URL to go to.
This process works using POSTMAN hitting the PHP, and it goes to the right page.
Opening Chrome Tools/Network, it shows that the PHP is returning a 302 and than a 200
My response object contains the full HTML for a page in the responseText property.
Funny thing is, if I hard code a bad URL,the browser goes to my 404 page fine.
Your thoughts? (Please don't ask me or tell me to use jQuery)
EDIT/ADDENDUM -----------------------
I have discovered that the redirect is using the same METHOD of the original call.
I'm doing
PUT /user/1
the Redirect is doing
PUT http://myserver.test/
This is the right place to go. Now I understand the 405.
I don't have a PUT route defined, therefore the 405.
I create a PUT route and it works in POSTMAN but still gives me a 405 in Chrome and Firefox.
I have 2 issues to solve:
1) change the METHOD on the redirect
2) figure out why the browser doesn't like the 307
I found "a" solution. I'm not sure I like it, but...
var xhr = new XMLHttpRequest();
xhr.open(method, url);
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.send(data);
xhr.onload = function (e) {
if (xhr.readyState === 4) {
window.location.replace(xhr.responseURL); // <---- solution
}
};
/* the following **frontend** function is invoked to
send a new post (in json) to the node server */
addPost(postData) {
const xhr = new XMLHttpRequest();
xhr.open('POST', `${process.env.REACT_APP_BACKEND}/posts`);
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.send(JSON.stringify(postData));
}
/* the following **server** code picks up the request
from the function above */
app.post('/posts', bodyParser.json(), (request, response) => {
new Promise(resolve => {
// code to add request.body to database will be here
resolve(request.body);
})
.then(data => response.send(data)); // *** How do I retrieve
} // *** this "data" in
); // *** my frontend code?
Hi all,
The top part of my code (frontend) is an ajax that sends a request in json format.
The bottom part of my code (node/express server) does the following:
1) receives the request
2) inserts "request.body" in a database
3) sends a response back to the frontend.
This response is a Promise containing the request.body. How do I retrieve this response in my frontend code? It seems that ajax helps me send requests, but doesn't do anything about retrieving the response that comes back.
Thanks!
P.S. Since this data was originally sent from the frontend, one might say the frontend already has this data. However, I just want to know, in general, how to retrieve a response when the request is sent by ajax.
const xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if (xhr.readyState == XMLHttpRequest.DONE) {
console.log(xhr.responseText);
}
}
xhr has an event handler onreadystatechange ,
you can say that the request has been successful when xhr.readyState == XMLHttpRequest.DONE.
more detailed doc on this can be availed # https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/readyState
you can also get the status code of the http request from xhr.status
XMLHttpRequest is pretty Useful API, but it is too low level, it is now being superseded by FETCH API, which is awesome, it also supports promise interface, that means you can use .then and .catch , or the newer async/await.
you can read it up here # https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API
and an example # https://googlechrome.github.io/samples/fetch-api/fetch-post.html
Today I researched about HTTP-methods and the differences between GET and HEAD in detail.
In theory I know, that HEAD only returns the HTTP header, not the HTTP body. Its useful to get information about ressources without downloading them completly.
I made a little Script using XHR to check out a HEAD-reques and tested it in Firefox 50.0.2.
http://codepen.io/anon/pen/oYqGMQ
var req = new XMLHttpRequest();
req.addEventListener("readystatechange", function () {
if (req.readyState === 4 && req.status === 200) {
alert("got response \n" + req.responseText);
}
}, false);
req.open("HEAD", location.href, true); // this is a HEAD-request, why I get a responseText?
req.send();
Why the HEAD-Request receives the complete data in the reponseText-property? I thought HEAD-Request will not receive any data of the body.
I can't see any difference between HEAD and GET.
Am I missing a point? I am using Firefox.
i try to make a Firefox Addon which runs a XMLHttp Request in Javascript. I want to get the data from this request and send it to *.body.innerhtml.
That's my code so far...
var xhr = new XMLHttpRequest();
xhr.open("GET", "http://xx.xxxxx.com", true);
xhr.send();
setTimeout(function() { set_body(xhr.responseHtml); }, 6000);
Instead of receiving the data, I get "undefined". If I change xhr.responseHtml to responseText I get nothing. I don't know why I'm getting nothing. I'm working on Ubuntu 12.04 LTS with Firefox 12.0.
If you need any more details on the script please ask!
Update:
set_body Function
document.body.innerHTML = '';
document.body.innerHTML = body;
document.close();
Update SOLVED:
I had to determine the RequestHeaders (right after xhr.open):
xhr.setRequestHeader("Host", "xxx");
For following Items: Host, Origin and Referer. So it seems there was really a problem with the same origin policy.
But now it works! Thanks to all!
when you set the last param of open to true you are asking for an async event. So you need to add a callback to xhr like so:
xhr.onReadyStateChange = function(){
// define what you want to happen when server returns
}
that is invoked when the server responds. To test this without async set the third param to false. Then send() will block and wait there until the response comes back. Setting an arbitrary timeout of 6 seconds is not the right way to handle this.
This code should work:
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function () {
if (xhr.readyState == 4) {
set_body(xhr.responseText);
}
};
xhr.open("GET", "http://xx.xxxxx.com", true);
xhr.send();
Make sure that you are getting a correct response from URL http://xx.xxxxx.com. You may have a problem with cross-domain calls. If you have a page at domain http://first.com and you try to do XMLHttpRequest from domain http://second.com, Firefox will fail silently (there will be no error message, no response, nothing). This is a security measure to prevent XSS (Cross-site scripting).
Anyway, if you do XMLHttpRequest from a chrome:// protocol, it is considered secure and it will work. So make sure you use this code and make the requests from your addon, not from your localhost or something like that.
I developed a small Javascript/jQuery program to access a collection of pdf files for internal use. And I wanted to have the information div of a pdf file highlighted if the file actually exist.
Is there a way to programmatically determine if a link to a file is broken? If so, How?
Any guide or suggestion is appropriated.
If the files are on the same domain, then you can use AJAX to test for their existence as Alex Sexton said; however, you should not use the GET method, just HEAD and then check the HTTP status for the expect value (200, or just less than 400).
Here's a simple method provided from a related question:
function urlExists(url, callback) {
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if (xhr.readyState === 4) {
callback(xhr.status < 400);
}
};
xhr.open('HEAD', url);
xhr.send();
}
urlExists(someUrl, function(exists) {
console.log('"%s" exists?', someUrl, exists);
});
Issue is that JavaScript has the same origin policy so you can not grab content from another domain. This won't change by upvoting it (wondering about the 17 votes).
I think you need it for external links, so it is impossible just with .js ...
If the files are not on an external website, you could try making an ajax request for each file. If it comes back as a failure, then you know it doesn't exist, otherwise, if it completes and/or takes longer than a given threshold to return, you can guess that it exists. It's not always perfect, but generally 'filenotfound' requests are quick.
var threshold = 500,
successFunc = function(){ console.log('It exists!'); };
var myXHR = $.ajax({
url: $('#checkme').attr('href'),
type: 'text',
method: 'get',
error: function() {
console.log('file does not exist');
},
success: successFunc
});
setTimeout(function(){
myXHR.abort();
successFunc();
}, threshold);
You can $.ajax to it. If file does not exist you will get 404 error and then you can do whatever you need (UI-wise) in the error callback. It's up to you how to trigger the request (timer?) Of course if you also have ability to do some server-side coding you can do a single AJAX request - scan the directory and then return results as say JSON.
Like Sebastian says it is not possible due to the same origin policy. If the site can be published (temporarily) on a public domain you could use one of the link checker services out there. I am behind checkerr.org
As others have mentioned, because of JavaScript's same origin policy, simply using the function from the accepted answer does not work. A workaround to this is to use a proxy server. You don't have to use your own proxy for this, you can use this service for example: https://cors-escape.herokuapp.com (code here).
The code looks like this:
var proxyUrl = "https://cors-anywhere.herokuapp.com/";
function urlExists(url, callback) {
var sameOriginURL = proxyUrl + url;
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if (xhr.readyState === 4) {
callback(xhr.status < 400);
}
};
xhr.open('HEAD', sameOriginURL);
xhr.send();
}
urlExists(someUrl, function(exists) {
console.log('"%s" exists?', someUrl, exists);
});