Implementing comet on the client side - javascript

I'm trying to implement comet in my application and, being inexperienced with JavaScript, I'm not sure how to do the client side.
When the server receives a request, it just keeps it open and writes data to it when necessary:
def render_GET(self, request):
print "connected"
request.write("Initiated\r\n")
reactor.callLater(random.randint(2, 10), self._delay, request)
return NOT_DONE_YET;
def _delay(self, request):
print "output"
self.count += 1
request.write("Hello... {0}\r\n".format(self.count))
reactor.callLater(random.randint(2, 10), self._delay, request)
I've been using jQuery on the client side so far, but I can't figure out how to make it work with the server. I've been looking at the jQuery.AJAX documentation and none of the callbacks say "Hey! I just received some data!", they only say "The request is finished."
I thought the dataFilter() function was what I wanted since it lets you handle the raw data before the request finishes, but it only lets you do it just before the request finishes, and not as you receive data.
So how can I receive data continuously through an open request? As you can see in the python example, each piece of data is delimited with \r\n so I want the JavaScript to behave like a line receiver. Is this possible with jQuery or do I have to play with XMLHttpRequest/ActiveXObject directly? Is there a (simple, lightweight) library available which implements a line receiver for me?
I'm hoping to hear about an existing library and how to implement this myself, since I've had bad bad luck with comet libraries so far, and at this point I'm hoping to just write the code I need and not bother with an entire library.

After looking at some other Comet/jQuery questions, I stumbled across this: http://code.google.com/p/jquerycomet/, which looks to be a jQuery plugin that does what you're after. If you're looking to see how it works, I'd just dig into the source.
The question where I found some great information is here.

A standard technique is to do a long polling request via AJAX (standard call with a really long timeout), then when receiving a response have your callback initiate another long poll when it is invoked. If the timeout expires, then you reissue the request using the error handling mechanism. Rather than having a single long request that periodically does something (like the "infinite iframe" technique), this uses a series of long requests to get data as the server has it available.
function longPoll( url, data, cb )
{
$.ajax({
url: url,
data: data,
timeout: Number.MAX_VALUE,
...other options...
success: function(result) {
// maybe update the data?
longPoll( url, data, cb );
cb.call(this,result);
},
error: function() {
longPoll( url, data, cb );
}
}
}

this code is the simpliest I have ever seen.
var previous_response_length = 0
, xhr = new XMLHttpRequest();
xhr.open("GET", "http://127.0.0.1:7379/SUBSCRIBE/hello", true);
xhr.onreadystatechange = checkData;
xhr.send(null);
function checkData() {
if(xhr.readyState == 3) {
response = xhr.responseText;
chunk = response.slice(previous_response_length);
previous_response_length = response.length;
console.log(chunk);
}
};

Related

Using JavaScript, is it possible to capture the body payload from an outgoing fetch request?

so I want to add some functionality to an already existing site, this is to make my life easier. One of the things I need that I can't seem to figure out is: how to capture the body payload data a specific outgoing "POST" request. I found the code to do it before but didn't save it and I been searching for that code for 2 days to no avail.
So here is an example of the request the site is making to server.
fetch("https://my.site/api/req", {"credentials":"include","headers":{"accept":"*/*","content-type":"application/json"},"referrerPolicy":"no-referrer-when-downgrade","body":"{\"symbol\":\"mySYM\",\"results\":[{\"data\":{\"id\":\"dataID\"},\"result\":\"signature\"}]}","method":"POST","mode":"cors"});
and the part I need to catch is the "body" portion and then unescape it so it looks like this.
{"symbol":"mySYM","results":[{"data":{"id":"dataID"},"result":"signature"}]}
Also, if possible I would like to have it only catch data when the method = POST and requests going to a specific URL, so it will catch /api/req/ and not pay attention to other URL's and/or when the method is = GET, HEAD.
Currently, I manually get the data from the request using dev tools and clicking on the correct request then scrolling down to find the POST data.
In case you need to know the reason for this. The server signs the data through the websocket connection and I am essentially trying to capture that signature to be able to replay it. I am not trying to catch the websocket data as its incomplete for my needs I need to catch the whole outgoing request body data.
Thanks in advance.
Chosen Solution:
Thanks #thirtydot for your responses. Note that my specific situation involved only fetch requests so that is the reason I went with this route. With your response, a bit of more of my own research, and the help of this post I came up with this solution. Since I don't really care to see the responses (I have other functions taking care of the responses which are important to me.).
const constantMock = window.fetch;
window.fetch = function() {
if (arguments[0] === '/api/req' && arguments[1].method === 'post'){
bodyResults(arguments[1].body)
}
return constantMock.apply(this, arguments)
}
function bodyResults(reqBody){
console.log(reqBody)
}
which put the following in console (Exactly as I wanted).
{"symbol":"NEON","results":[{"data":{"expires_at":"1561273300","id":"2469c8dd"},"signature":"6d712b9fbb22469c8dd240be13a2c261c7af0dfbe3328469eeadbf6cda00475c"}]}
except now I can return this data through that function and continue to run the rest of my script fully automated.
Extra Solution:
In case there are others struggling with similar issues and care to catch the responses of those fetch requests I could have alternatively used:
const constMock = window.fetch;
window.fetch = function() {
if (arguments[0] === '/api/req' && arguments[1].method === 'post'){
bodyResults(arguments[1].body)
}
return new Promise((resolve, reject) => {
constantMock.apply(this, arguments)
.then((response) => {
if(response.url.indexOf("/me") > -1 && response.type != "cors"){
console.log(response);
// do something for specificconditions
}
resolve(response);
})
.catch((error) => {
reject(response);
})
});
}
function bodyResults(reqBody){
console.log(reqBody)
}
Possible XHR Solution
NOTE: this one is untested! An alternative Solution for XHR requests could be done similarly using something along the lines of:
(function(open) {
XMLHttpRequest.prototype.open = function(method, url, async, user, pass) {
alert('Intercept');
open.call(this, method, url+".ua", async, user, pass);
};
})(XMLHttpRequest.prototype.open);
Hope this helps!
So I came across this today and I'm not quite sure if its exactly what you've been looking for over 2 years ago, but solved my problem and I thought I should share it if others needed.
I'm currently using a marketing automation tool which is quite limiting when it comes to landing pages, but I wanted the client to be able to update the content whenever needed and still have access to custom functionality, so I needed the payload which was being sent by the form submission.
Here is what I used to get the form submission payload:
(function() {
var origOpen = XMLHttpRequest.prototype.send;
XMLHttpRequest.prototype.send = function() {
console.log('request started!');
console.log(arguments[0]);
this.addEventListener('load', function() {
console.log('request completed!');
console.log(this.status);
});
origOpen.apply(this, arguments);
};
})();
The arguments[0] piece is actually the JSON sent as the payload, and the status code is the response (200), stating the request was successfull.
I partially used code from this other response here: https://stackoverflow.com/a/27363569/1576797

How to use XMLHttpRequest while telling site to do something?

First of all I have to say that I have NO EXPERIENCE in Ajax and I just need this one explanation in order for me to create a simple chrome extension.
There is not much I could find on internet even tho I believe this is very simple.
I need a part of code where I would "call" url from website and I need to adjust certain arguments in that url.
Request URL:http://URL_OF_THE_WEBSITE/v1/send?token=TOKEN_VALUE
Request Method:POST
Request Payload :
{amount: 1, user_id: 12345678}
amount: 1
user_id: 12345678
(this is something I get from Network panel- with url and token changed to real things - while calling url automatically from website, but I need to be able to call it manually too.)
So I have an idea of mixing AJAX(which I don't know) and JS in order for me to call this url.
I would use variables for both TOKEN_VALUE and amount&user_id, but I don't know how to even call that url and how to set "request payload" in order for site to do the thing I want it to do.
I would really appreciate if someone would be kind enough to help :)
Work I have done, but doesn't work:
var request=new XMLHttpRequest;
request.open("POST","https://URL_OF_THE_WEBSITE/v1/send?token=TOKEN_VALUE"),request.setRequestHeader("Content-Type","application/x-www-form-urlencoded;charset=UTF-8"),request.Payload("user_id=12345678&amount=5");
I basically tried to remake an example I found online, but it didn't work out, therefore I need someone to actually explain to me how this works and how can I adjust arguments that I need.
function callAjax() {
// the XMLHttpRequest returns the ajax object that has several cool methods, so you store it in the request variable
// #data contains the $_POST[amount],$_POST[user_id],$_POST[whatever] since we are using POST method, if you're using PHP as a server side language
var request = new XMLHttpRequest(),
url = 'place_here_the_url_only',
data = 'amount=1&user_id=12345678&whatever=dataYouWantToSendToServerFromBrowser',
token = document.querySelector('meta[name="csrf-token"]').content;
// when the server is done and it came back with the data you can handle it here
request.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
// do whatever you want!
console.log("The request and response was successful!");
}
};
// method post, your giving it the URL, true means asynchronous
request.open('POST', url, true);
// set the headers so that the server knows who is he talking to, I'm using laravel 5.5
request.setRequestHeader('Content-type', 'application/x-www-form-urlencoded; charset=UTF-8');
// Token needed
request.setRequestHeader('X-CSRF-TOKEN', token);
// then you send the data and wait for the server to return the response
request.send(data);
}
Ajax: Asynchronous JavaScript And XML
It is a mean of communication between the browser and the server hosting the website, it cannot call any other server.
Asynchronous means the website continues to function normally, until the request is returned from the server and the:
if (this.readyState == 4 && this.status == 200) { }
gets triggered

Javascript (no JQuery) function that retrieves JSON objects from different URLs?

I've been looking for an AJAX function that receives an URL and then returns the JSON object.
Let's say I need to display some Users info from a JSON in URL1 and also mix that display with some Posts info from a JSON in URL2.
I'll like to do this without JQquery.
Let's say something like this:
function loadJSON(path, success, error)
{
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function()
{
if (xhr.readyState === XMLHttpRequest.DONE) {
if (xhr.status === 200) {
if (success)
success(JSON.parse(xhr.responseText));
} else {
if (error)
error(xhr);
}
}
};
xhr.open("GET", path, true);
xhr.send();
}
function getInfo(){
var users, posts;
loadJSON('http://.com/users',
function(dataU) {
users = dataU;
},
function(xhr) { console.error(xhr); }
);
loadJSON('http://.com/posts',
function(dataP) {
posts = dataP;
},
function(xhr) { console.error(xhr); }
);
console.log(users);
console.log(posts);
}
getInfo();
To achieve this without jQuery, you can fall back to plain JavaScript XMLHttpRequests. This will allow you to establish an HTTP connection with a remote host and e.g. GET data.
To get started with those requests, you can have a look at MDN's getting started guide.
The JSON.parse() function will help you convert the JSON string into a JavaScript object.
As an alternative to XMLHttpRequests, you can also look into the fetch API. It provides a cleaner interface for HTTP calls. Since it is still experimental however, you may want to use a polyfill.
With or without jQuery the XMLHttpRequest objest is asynchronous. jQuery uses it internally. FIY AJAX stands for Asynchronous Javascript And Xml. It means that you cannot receive a synchronous result from an asynchronous function. But you can and should use the result in a callback function you send to the request.
So correct usage is to call console.log (or whatever you want) from success or error callbacks.
There are known solution how to degrade gracefully when XMLHttpRequest is not available. Among these solutions are create and append script or iframe and then read from their .onload handlers. All of them are asynchronous and all previous considerations apply directly to them.
You Cannot Receive Synchronous Result From Asynchronous Function.
I hold this truth against all downvotes.

vanilla js vs jQuery ajax call

I want to do an ajax call with vanilla js.
In jQuery, I have this working ajax call:
$.ajax({
url:"/faq/ajax",
datatype: 'json',
type:"POST",
data: {search:'banana'},
success:function(r) {
console.log(r['name'])
}
});
Vanilla JS:
var search = document.getElementById('searchbarfaq').value;
var r = new XMLHttpRequest();
r.open("POST", "/faq/ajax", true);
r.onreadystatechange = function () {
if (r.readyState != 4 || r.status != 200) return;
console.log("Success: " + JSON.parse(r.responseText));
var a = JSON.parse(r.responseText);
console.log(a.name); //also tried a['name']...
};
r.send("search=banana");
The vanilla js call just logs this to the console:
"Success: [object Object]"
Array [ ]
Can someone tell me what I am doing wrong?
You haven't told the server how you are encoding the data in the request.
r.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
Presumably whatever server side handler you are using to process the data isn't parsing it correctly, so isn't finding the data it needs, and then returns a blank array as the result.
Beyond printing out r.responseText to the console, you can also inspect the HTTP response from dev tools built into the browser itself.
On Firefox, for instance:
Tools -> Web Developer -> Network
(this should open a panel listing all the HTTP requests and responses)
Go through the process you use to execute your AJAX call
Look at the corresponding HTTP request by clicking on the item in the list in the panel shown in step 1 (a panel on the right should appear with more details about the request and subsequent response)
Digging around in these tools can give you a lot of insight into the the HTTP request your code is making and the values it's getting back in the response.
A similar process can be performed for all the major browsers out there.
You can use this simple and lightweight Ajax module with the following syntax:
import {ajax} from '/path/to/ajax.min.js';
ajax('https://api_url.com')
.data('key-1','Value-1')
.data('key-2','Value-2')
.send()
.then((data) => { console.log ('success', data) })
.catch((status) => { console.log ('failed', status)} );

Example of using github API from javascript

I've been searching on the web for some time and couldn't find an example of how to use the GitHub API from plain client-side javascript (no node-js, jquery etc). I wanted something like authenticate then push a blob, put as simply as possible so I can understand it. Shouldn't be too complicated, I bet you can do that in a dozen lines of code but I don't know a lot about ajax, json and jsonp.
Can you provide an example to get me started?
Thanks!
edit: found this: http://blog.vjeux.com/category/javascript, but I'm still confused as to what are exactly the steps of the process.
If you're looking to use with vanilla JavaScript (i.e. no framework), you need to play around with the XMLHttpRequest object. The XMLHttpRequest provides the core for AJAX implementations.
Despite the XMLHttp prefix, you're not limited to XML or HTTP. You can retrieve any data type (such as JSON) and use other protocols such as FTP.
Say we'd like to GET your user information from GitHub. From a browser, we can easily make the request by visiting https://api.github.com/users/funchal.
Sending an HTTP request in JavaScript is just as simple with XMLHttpRequest:
// Create a new request object
var request = new XMLHttpRequest();
// Initialize a request
request.open('get', 'https://api.github.com/users/funchal')
// Send it
request.send()
If you give this a go from a JavaScript console, you might feel a bit disappointed: nothing will happen immediately. You'll have to wait for the server to respond to your request. From the time you create the instantiate the request object till when the server responds, the object will undergo a series of state changes denoted by the value of the readyState property:
0 UNSENT: open() uncalled
1 OPENED: send() uncalled
2 HEADERS_RECIEVED: headers and status are available after a send()
3 LOADING: the responseText is still downloading
4 DONE: Wahoo!
Once all is finished, you can check the response attribute for the data:
request.readyState // => 4 (We've waited enough)
request.response // => "{whatever}"
When using XMLHttpRequest#open(), you have a few options to consider. Here's the method signature:
void open(
DOMString method,
DOMString url,
optional boolean async,
optional DOMString user,
optional DOMString password
);
The third parameter, which defaults to true, dictates whether the response should be made asynchronously. If you set this to false, you'll have to wait until the response is complete for #send() to return, and you'll pay the price of blocking your whole program. As such, we code in an asynchronous fashion so that our program remains responsive even while we wait. This asynchronicity is achieved by using and event listeners (a.k.a. event handlers) and callback functions.
Say we want to simply dump the response to the console once it arrives. We first need to create a callback function that we'd like to execute onload:
function dumpResponse() {
// `this` will refer to the `XMLHTTPRequest` object that executes this function
console.log(this.responseText);
}
Then we set this callback as the listener/handler for the onload event defined by the XMLHttpRequest interface:
var request = new XMLHttpRequest();
// Set the event handler
request.onload = dumpResponse;
// Initialize the request
request.open('get', 'https://api.github.com/users/funchal', true)
// Fire away!
request.send()
Now since you'll be receiving the data as a string, you'll need to parse the string with JSON.parse() to do anything meaningful. Say I want to debug the number of public repositories you have along with your name. I can use this function to parse the string into JSON, and then I can pull the attributes I want:
function printRepoCount() {
var responseObj = JSON.parse(this.responseText);
console.log(responseObj.name + " has " + responseObj.public_repos + " public repositories!");
}
var request = new XMLHttpRequest();
request.onload = printRepoCount;
request.open('get', 'https://api.github.com/users/funchal', true)
request.send()
// => Giovanni Funchal has 8 public repositories!
See the W3C spec and the Mozilla Developer Network for more info on XMLHttpRequest.

Categories