I am trying to create a JavaScript code that allows me to check if I can send an HTTP request to the given host, through an URL (check if the server on or not). This is my code:
<html>
<body>
<script>
function checkServer(url) {
const controller = new AbortController();
const signal = controller.signal;
const options = { mode: 'no-cors', signal };
return fetch(url, options)
.then(setTimeout(() => { controller.abort() }, 5))
.then(response => function()
{
var xhttp = new XMLHttpRequest();
xhttp.open("GET", "http://log.mywebsite.com", true);
xhttp.send();
}
)
.catch(error => function()
{
var xhttp = new XMLHttpRequest();
xhttp.open("POST", "http://log.mywebsite.com", true);
xhttp.send();
}
)
}
checkServer('https://blahdummydamnfck.com');
</script>
</body>
</html>
But, although it can't send the HTTP request to the server, it didn't send a log request to my log server. Why is this happening with me?
the fetch does not throw. It returns an error code if the request fails, so catch is not the right way to detect a missing server. Check the response code instead
from the manual:
The fetch() method takes one mandatory argument, the path to the resource you want to fetch. It returns a Promise that resolves to the Response to that request, whether it is successful or not. You can also optionally pass in an init options object as the second argument (see Request).
Related
I have a function as the code below, I am trying to send a file through XMLHttpRequest to the server and then store it in DB and retrieve the id of the file in DB and make an object of ids.
The problem is that the function exits a lot before I got the response back from the server to store it in the object therefore the object doesn't store those values.
I know that I need make the XHR asynchronous but it doesn't change the result, I have also tried timeout or using a different platform like Ajax but still, it didn't work.
async function getFileObj() {
var FileObject = {}
for (let key1 in PObj) {
FileObject[key1] = {}
for (let key2 in PObj[key1]) {
FileObject[key1][key2] = {}
for (let key3 in PObj[key1][key2]) {
const formData = new FormData();
formData.append('myFile.png', filesObjDB[key1][key2][key3]);
var xhr = new XMLHttpRequest();
xhr.open("POST", 'url', true);
xhr.onreadystatechange = async function() {
if (this.readyState === XMLHttpRequest.DONE && this.status === 200)
var id = await xhr.response.text();
FileObject[key1][key2][key3] = parseInt(id)
}
xhr.responseType = 'blob';
xhr.send(formData);
}
}
}
return FileObject;
}
Help would be very appreciated!
You are not awaiting the request. To make the existing code wait for the result, you'd need to wrap the outdated callback-based code in a promise and await that (and also I don't think getting the response text of an XHR works as you showed, I changed it now):
// This is just to demonstrate what was immediately wrong
// with the existing code - it's not the best solution! See below.
FileObject[key1][key2][key3] = await new Promise((resolve, reject) => {
var xhr = new XMLHttpRequest();
xhr.open("POST", url, true);
xhr.onreadystatechange = function() {
if (this.readyState === XMLHttpRequest.DONE && this.status === 200) {
var id = xhr.responseText;
resolve(parseInt(id));
}
};
xhr.send(formData);
});
Note there is no error handling yet, if the request fails everything will just hang.
But at that point, it doesn't actually make sense to use XHR in the first place! It's a lot more straightforward to use fetch, which has a promise API out of the box:
const response = await fetch(url, { method: 'POST', body: formData })
FileObject[key1][key2][key3] = parseInt(await response.text())
I have server and a client the server uses node js the client send requests to the sever and the server should act accordingly.
However I came across a little bit of a confusing behavior and i want to know why its behaving like that!
The thing is when i send a json array or Object the received data by the server is always empty for some reason.
Here is the code of the request that raises the problem:
function Save()
{ // saves the whole global data by sending it the server in a save request
if( global_data.length > 0)
{
var url = "http://localhost:3000/save";
var request = new XMLHttpRequest();
request.open("POST", url, true);
request.setRequestHeader("Content-Type", "application/json");
request.onreadystatechange = function () {
if (request.readyState === 4 && request.status === 200) {
console.log(this.responseText);
}
};
let object={ id: "101.jpg", RelativePath: "images/101.jpg", size: 61103 }; // this just an exemple of data
let data_json = JSON.stringify(object);
request.send(data_json);
}
else
{
console.log("Nothing to save");
}
}
And Here is the server code related to this request:
const server=http.createServer(onRequest)
server.listen(3000, function(){
console.log('server listening at http://localhost:3000');
})
function onRequest (request, response) {
/*function that handles the requests received by the server and
sends back the appropriate response*/
/*allowing Access-Control-Allow-Origin since the server is run on local host */
response.setHeader('Access-Control-Allow-Origin', '*');
response.setHeader('Access-Control-Request-Method', '*');
response.setHeader('Access-Control-Allow-Methods', 'OPTIONS, GET');
response.setHeader('Access-Control-Allow-Headers', '*');
console.log("a request received :" ,request.url);
let parsed_url = url.parse(request.url);
if(parsed_url.pathname == '/save')
{
console.log("Proceeding to save state : ...");
let received_data = '';
request.on('data', function(chunck) {
received_data += chunck;
console.log("another line of data received");
});
request.on('end', function() {
console.log(received_data); // why is this empty (my main problem)?
let jsondata = JSON.parse(received_data); // here raises the error since the received data is empty
console.log(jsondata);
response.writeHeader(200,{"content-Type":'text/plain'});
response.write("SAVED!");
response.end()
});
}
}
Just if anyone got the same problem: for me I couldn't solve it directly so I was forced to use query-string in order to parse the data instead of json.parse it seems the data received emptiness was related to the failure of the JSON parser somehow. so I installed it with npm install querystring and used const qs = require('querystring'); in order to invoque the parser by calling qs.parse(received_data.toString());.
Hope this helps anyone who got stuck in the same situation.
What's this crap?
This code here sends the data through the POST request. I know that because my Node server receives chunks.
let req = new XMLHttpRequest();
req.onload = () => {
console.log("Done");
};
req.open('POST', location.origin + ':1337');
req.send('test');
All good and normal.
HOWEVER. The second I change it to this
let req = new XMLHttpRequest();
req.onload = () => {
console.log("Done");
};
req.upload.onprogress = (e) => {
console.log("Progress");
};
req.open('POST', location.origin + ':1337');
req.send('test');
, it doesn't send the data anymore.
My Node server isn't special. It's simply an httpServer instance running on :1337, console.log-ing received data chunks.
What's going on here? Why would the listener disrupt the request?
Turns out adding a listener makes the browser send an OPTIONS request beforehand. I wasn't properly responding to that, now I am.
Thanks #sideshowbarker!
This is part of the code for the extension:
let url = "https://mywebsite.com/data.php";
function newRequest() {
var client = new XMLHttpRequest();
client.open("POST", url, true);
client.setRequestHeader("Content-Type", "text/plain;charset=UTF-8");
client.send("status=true");
console.log(client.status);
}
newRequest();
Which also logs 0 in the console. I've been following the documentation here: https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest, trying countless tweaks, and there aren't any errors in the console. Not really sure what the issue could be.
The PHP on my server definitely works since I was able to POST the data successfully from a local html file.
Since the AJAX request is asynchronous, you need to handle it through a callback onreadystatechange.
The code should be like this
let url = "https://mywebsite.com/data.php";
function newRequest() {
var client = new XMLHttpRequest();
client.onreadystatechange = function() {
console.log(this.readyState) // should be 4
console.log(this.status) // should be 200 OK
console.log(this.responseText) // response return from request
};
client.open("POST", url, true);
client.setRequestHeader("Content-Type", "text/plain;charset=UTF-8");
client.send("status=true");
console.log(client.status);
}
newRequest();
Hope this helps.
For More Info: https://www.w3schools.com/js/js_ajax_http_response.asp
I am using the following code to hook into XMLHttpRequest open/send methods:
var lastParams = '';
var send = XMLHttpRequest.prototype.send;
XMLHttpRequest.prototype.send = function(data){
lastParams = data;
send.call(this, data);
};
var open = XMLHttpRequest.prototype.open;
XMLHttpRequest.prototype.open = function(method, uri, async, user, pass) {
this.addEventListener("readystatechange", function(event) {
if(this.readyState == 4){
var self = this;
var response = {
method: method,
uri: uri,
params: lastParams,
responseText: self.responseText
};
console.log(response);
}
}, false);
open.call(this, method, uri, async, user, pass);
};
It is working fine in the case of single ajax request at a time.
When multiple ajax request are firing at a time, then lastParams can contain wrong data (means lastParams can contain data from other ajax request). I want to uniquely associate the lastParams with request's other attributes?
Is there any id attribute in XMLHttpRequest so that I can uniquely identify the ajax request instance?
Thanks in advance.
Have a look at https://github.com/jpillora/xhook and the demos
//modify 'responseText' of 'example2.txt'
xhook.after(function(request, response) {
if(request.url.match(/example\.txt$/)) {
response.text = response.text.replace(/[aeiou]/g,'z');
}
});
For uniquely associating some data with specified XMLHttpRequest instance you can simply add property into XMLHttpRequest instance and save data into property. For example:
// generating data for request
var data=generateData();
// sending data
var xhr=new XMLHttpRequest();
xhr.open("POST","/yourpage.php",true);
xhr.onreadystatechange=function(event){
if(this.readyState===4){
console.log(this.mySendedData);
}
};
/** if you need to preserve 'data' variable value for each xhr **/
xhr.mySendedData=data;
/***************************************************************/
xhr.send(data);
why not make 'lastParams' as an array, and you always push data, instead of overwriting it everytime.