I'm sending chunked data from a NodeJS application back to the browser. The chunks are really json strings. Problem I'm having is that every time the onprogress function is called, it adds on a string of the complete data. Meaning that response chunk number two, is appended to response chunk number one, and so on. I'd like to get ONLY the "just now" received chunk.
Here's the code:
console.log("Start scan...");
var xhr = new XMLHttpRequest();
xhr.responseType = "text";
xhr.open("GET", "/servers/scan", true);
xhr.onprogress = function () {
console.log("PROGRESS:", xhr.responseText);
}
xhr.send();
So really, the contents of xhr.responseText contains, when the third response comes, also the response text for the first and the second response. I've checked what the server is sending, and it doesn't look like there's a problem there. Using Node with Express, and sending with res.send("...") a couple of times. Also headers are set like so:
res.setHeader('Transfer-Encoding', 'chunked');
res.setHeader('X-Content-Type-Options', 'nosniff');
res.set('Content-Type', 'text/json');
This index based approach works for me:
var last_index = 0;
var xhr = new XMLHttpRequest();
xhr.open("GET", "/servers/scan");
xhr.onprogress = function () {
var curr_index = xhr.responseText.length;
if (last_index == curr_index) return;
var s = xhr.responseText.substring(last_index, curr_index);
last_index = curr_index;
console.log("PROGRESS:", s);
};
xhr.send();
Inspired by https://friendlybit.com/js/partial-xmlhttprequest-responses/
Related
I am trying to return a webpage, and grab the part of the page labeled: Description. I want to be able to split the returned HTML, but with the "" that are in HTML it will not work correctly.
This is for a template to allow a user on an extension to be able to add a pre-loaded string to fill in a box. I have tried splitting the string at a set word, but my knowledge does not extend past trying to use the string.
function pullWebpage(){
var data = null;
var xhr = new XMLHttpRequest();
xhr.withCredentials = true;
xhr.addEventListener("readystatechange", function () {
if (this.readyState === 4) {
var response = this.responseText;
response.split("Description");
console.log(response);
}
});
xhr.open("GET", "https://jira2.cerner.com/browse/ION-25843?", true);
xhr.setRequestHeader("Cache-Control", "no-cache");
xhr.setRequestHeader("cache-control", "no-cache");
xhr.send(data);
}
I want to be able to successfully pull out the description of the page pulled in the GET, and use this to set up an automatic template. HTML returned in GET using postman here
While the issue before was based on grabbing the whole HTML, using the rest api was a better solution. Changing the code to:
var data = null;
var xhr = new XMLHttpRequest();
xhr.withCredentials = true;
xhr.addEventListener("readystatechange", function () {
if (this.readyState === 4) {
var response = JSON.parse(this.responseText);
console.log(response.fields.description);
}
});
xhr.open("GET", "https://jira2.cerner.com/rest/api/2/issue/ION-25843");
xhr.setRequestHeader("Content-Type", "application/json");
xhr.send(data);
Allows for the code to go out and grab the json of the page, and then grab the specific definition of the page.
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 have a text file on my server and I want to upload a text in it using XMLHttpRequest. It is downloaded successfully via GET method, but when I try to POST it I get 404 error.
var r1 = new XMLHttpRequest();
r1.open("GET", "db.txt", false);
r1.send();
var str = r1.responseText + "foo text";
var r2 = new XMLHttpRequest();
r2.open("POST", "db.txt", false);
r2.send(str);
Doing a direct upload as you're trying would be a security concern in most places and is generally not permitted... What you need to do is have a middle layer on your server to handle the request and write the file to disk safely.
You can easily upload a file using something like this:
var jsonBlob = new Blob([someJSON], {type: "text/plain;charset=utf-8"});
var data = new FormData();
data.append("filename", "new.json");
data.append("json", jsonBlob);
var xhr = new XMLHttpRequest();
var postURL = "http://example.com/post_target";
xhr.open("POST", postURL, true);
xhr.onload = function(e) {
if (this.status == 200) {
console.log(e.target.response);
}
};
xhr.send(data);
Where postURL is an endpoint which can handle file uploads.
If you post what language(s) you have available on your server (PHP?) I can give some example code to handle the upload on the server's end.
Give a HTTP Filesystem API which accepts
GET /storage/filename
PUT /storage/filename
Request body: the file contents
and these headers
Content-Length: ...
Content-Type: application/octet-stream
How can one build a backbone.js File Model which works with it? (e.g. get file contents in a variable, put back updated contents)
If backbone.js doesn't support this, how would jQuery ajax requests look like?
While I haven't found support in jQuery/backbone, here's how it can be done:
var xhr = new XMLHttpRequest();
xhr.open('GET', "url", true);
xhr.setRequestHeader("Authorization", token);
xhr.responseType = "text";
xhr.onload = function(e) {
if (this.status == 200) {
var contents = this.response;
console.log("RECEIVED " + contents);
}
};
xhr.send();
More details at http://www.html5rocks.com/en/tutorials/file/xhr2/