response cookies and 2 asynchronous xmlhttp request using chrome.cookies extension - javascript

I have 2 different XMLHttpRequest objects making asynchronous requests to the same web service. The web service sends back a cookie in the HTTP response headers, that I can read with the chrome.cookies.read extension (the request is cross-domain).
Each xhr reads the same cookie by name, but the value of the cookie after each response will be different, as it is a unique token for each requester.
So I want to store each cookie value per request, just after receiving the HTTP response, for later use.
So here's what my code is currently doing:
var my_cookie_value = [] ;
function begin()
{
for (var i = 0 ; i < 2 ; i ++)
{
sendRequest(some_url, i);
}
}
function sendRequest(some_url, thread)
{
var xmlhttp=new XMLHttpRequest();
xmlhttp.onreadystatechange=function()
{
if (xmlhttp.readyState == 4 && xmlhttp.status == 200)
{
readCookie(thread) ;
}
}
xmlhttp.open("GET", some_url, true);
xmlhttp.send();
}
function readCookie(thread)
{
chrome.cookies.get(
{
"url" : some_domain,
"name" : "mycookie"
},
function(cookie)
{
if (cookie != null)
{
my_cookie_value[thread] = cookie.value ;
}
}
);
}
However because chrome.cookies.read uses a callback function with no guaranteed time to fire, I am finding the cookie values get mixed up (or repeated) for each thread, even though they were returned from the server as distinct values.
I think what can happen is:
thread 0 sends request
thread 1 sends request
thread 0 receives response
thread 0 requests cookie value callback
Arrgghh!!...worst case scenario coming up...
thread 1 receives response
thread 1 requests cookie value callback
thread 0 cookie callback fires and cookie value (FOR THREAD 1) is copied into my_cookie_value[0]
thread 1 cookie callback fires and cookie value (FOR THREAD 1) is copied into my_cookie_value[1]
This is obviously not what I wanted. my_cookie_value[0] and [1] both contain the token for thread 1.
So finally to the question: Is there another solution for this? I cannot rewrite the server code, I can only access the client.
I am wondering why oh why is reading a cookie done by a callback function??

Set up var that tracks if you currently have a request active. Something like var currentRequest = false and set it to true before starting a request and set it to false after a request is complete. Before starting a request check if there is an active request and if there is either delay or create a queue of pending requests.

Related

Javascript XMLHTTPRequest send with protocol undefined in header

I am trying to debug a functionality that runs from a plain old Javascript Web Page and requests to a server.
This perfectly works on my computer but fails on another (the real target)
When it fails, i get an empty string response from the server.
Here is the code that build the request
// Send request to web server
var url = "/start?f="+filesDesc[iFile].name+"&ft="+ft+"&t="+time0ms;
var req = new XMLHttpRequest();
if (req) {
req.open("POST", url, true);
// Hack to pass bytes through unprocessed.
req.overrideMimeType('text/plain; charset=x-user-defined');
req.timeout = 2000;
req.onreadystatechange = function(e) {
// In local files, status is 0 upon success in Mozilla Firefox
if(req.readyState === XMLHttpRequest.DONE) {
var status = req.status;
if (status === 0 || (status >= 200 && status < 400)) {
// The request has been completed successfully
console.debug(req.responseText);
} else {
console.debug("startPlaying : error while sending rqst" );
}
}
};
req.send();
}
I noticed that on my computer (working) the output header of the request looks like this :
POST /start?f=2021-02-09_14;05;40&ft=1612880820756.4346&t=1614243685530 HTTP/1.1
On the target computer (FAIL) it looks like :
POST /start?f=2021-02-09_14;05;40&ft=1612879543815&t=1614183852864 undefined
Notice the "undefined" protocol information
I wonder what can produce such a difference knowing that :
The computer are the same 'Asus ZenBook'
Navigator are the same : Mozilla Firefox 85.0.2 (32 bits)
Network drivers are the same
Client and Server code are the same.
This is very strange behaviour.
Many thanks for any precious piece of information !
We find out that this behaviour was a side effect of a DOM exception caused by registering activeX filters. Our application also tried to load video with calls to :
navigator.mediaDevices.getUserMedia({video: { deviceId: device.deviceId }})
This was ending in an :
Uncaught DOMException: A network error occured.
Believe me or not, removing activeX filters removes the network error !
We felt into a problem similar to :
NotReadableError: Failed to allocate videosource

How to remove automatically added connections proxy in XCC?

I want to make an ajax request from IBM Connections XCC:
let api = 'https://my-server2/api.xml'
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = () => {
if (xmlhttp.readyState == XMLHttpRequest.DONE)
if (xmlhttp.status == 200) {
console.log(xmlhttp.responseText)
}else {
console.log(`Error: ${xmlhttp.readyState}`)
}
}
Result in the network tab is a request to https://connections-host/communities/ajaxProxy/https/my-server2/api.xml so the request is proxied over the connections server. Because of this I get an empty API result since I need an authorized user session. My idea was: The user is logged in in his browser on my-server2 application. So when making an ajax request to my-server2, I can get the API information in his user context.
So my question is: How can I bypass those proxy?
Since I don't set it, I assume that connections manipulate the XMLHttpRequest class in a way like this: https://gist.github.com/dewdad/8830348
I want to view it's code to see the manipulation with this code in the console, but it only shows native code
window.XMLHttpRequest.prototype.open.toString()
"function open() {
[native code]
}"
Connections uses an AJAX proxy to control what's sent out to non-Connections sites/apps. You can configure it for your site to allow specific methods, headers and cookies to be sent to the non-Connections site. I'd take a look at this document on Connections 6.0 https://www.ibm.com/support/knowledgecenter/en/SSYGQH_6.0.0/admin/secure/t_admin_config_ajax_proxy_feature.html
I think that should help you get what you want.

Is it possible to retry an XMLHttpRequest that I Intercepted?

I am overriding the XMLHttpRequest.prototype.send = function(a,b) { } and XMLHttpRequest.prototype.open = function(a,b) { } so I can intercept every single response I get from every ajax call. Sometimes, some of those requests fail, and when that happens I need to update the cookies for the DOM and retry the failed original XHRs.
Taking in consideration that I have no control over those XHRs, meaning that I don't create them, or execute them, would it be possible for me to retry those XHR with new updated cookies?
Right now, I save the original XHR in a new variable, and when it fails, I do an xhr.open.apply() and then xhr.send.apply(). Using an HTTP Web Proxy like Charles I am able to check my response and I always get error message: Invalid request... I also realized that the difference between the original XHR and the retried XHR is that the X-Request-With header is always missing.
Any ideas on how to solve this issue?
Well, it is possible and I managed to do it.
I created a function to retry the original request, where I pass the same parameters that were passed to the XMLHTTPRequest.prototype.send function that intercepted the XMLHTTPRequest before being send.
function retryOriginalRequest(a,b, args) {
var originalRequest = new XMLHttpRequest();
originalRequest.open(a,b, true);
// The request headers need to be set up after the open call and before the send.
originalRequest.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
originalRequest.send(args, null);
};

CORS error when accessing local JSON file using vanilla JS AJAX request?

I am trying to use a vanilla JS AJAX request to pull back a JSON string from a locally stored JSON file (specifically trying not to use JQuery) - the below code is based on this answer - but I keep getting an error in the Chrome console (see below). Any ideas where I'm going wrong? I have tried changing the positioning of the xhr.open & .send requests, but still get error messages. I suspect the issue lies with the .send() request?
//Vanilla JS AJAX request to get species from JSON file & populate Select box
function getJSON(path,callback) {
var xhr = new XMLHttpRequest(); //Instantiate new request
xhr.open('GET', path ,true); //prepare asynch GET request
xhr.send(); //send request
xhr.onreadystatechange = function(){ //everytime ready state changes (0-4), check it
if (xhr.readyState === 4) { //if request finished & response ready (4)
if (xhr.status === 0 || xhr.status === 200) { //then if status OK (local file || server)
var data = JSON.parse(xhr.responseText); //parse the returned JSON string
if (callback) {callback(data);} //if specified, run callback on data returned
}
}
};
}
//-----------------------------------------------------------------------------
//Test execute above function with callback
getJSON('js/species.json', function(data){
console.log(data);
});
The console in Chrome is throwing this error:
"XMLHttpRequest cannot load file:///C:/Users/brett/Desktop/SightingsDB/js/species.json. Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-extension, https, chrome-extension-resource."
Would be grateful for any insights - many thanks.
Basically as Felix, error msg, et al below say - simply can't run an AJAX request against a local file.
Thanks.
Try to run the application on local server like apache or wamp then you will not face any issue

How can I tell XHR is sent to server using readyState?

This question is related to my prior question:
Is READYSTATE_LOADED across browsers?
So I know that readyState is not reliable across browsers. I'm currently just trying to do a proof-of-concept in ANY browser at this point.
I'm in my plugin and have code like this:
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function(){
if (xhr.readyState == 4){
self._onComplete(id, xhr);
}
else if (xhr.readyState == 2 ){
self._onSent( id, xhr );
}
};
If I log the callbacks, "sent" fires immediately before "complete", AFTER my server side script responds. Am I misunderstanding what readyState 2 is? I tried 1 for kicks and that didn't fire before the server responded either.
I took a look into the upload object of the xhr object, which does at least have a "progress" event, but I still didn't see anything about progress being done. In fact if the last progress was at 97%, it will not fire at 100% as the file completes sending to server. Therefore while the server processes the upload, the progress hangs at 97% before the readyState becomes 4.
This makes the user think the upload stalled even thought it actually went up all the way.
There is no state to check to see when a request has been sent off.
readyState 2 means that the server has responded and all headers have come in. This is fired right before the main body section of the request comes in.
Your best bet is to fire your own event when you issue the send() command.
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function(){
if (xhr.readyState == 4){
self._onComplete(id, xhr);
}
else if (xhr.readyState == 2 ){
// Headers received
}
};
xhr.send(data)
self._onSend( id, xhr );
4.6 States
UNSENT (numeric value 0) The object has been constructed.
OPENED (numeric value 1) The open() method has been successfully
invoked. During this state request headers can be set using
setRequestHeader() and the request can be made using the send()
method.
HEADERS_RECEIVED (numeric value 2) All redirects (if any) have been
followed and all HTTP headers of the final response have been
received. Several response members of the object are now available.
LOADING (numeric value 3) The response entity body is being received.
DONE (numeric value 4) The data transfer has been completed or
something went wrong during the transfer (e.g. infinite redirects).
http://www.w3.org/TR/XMLHttpRequest/#states
EDIT
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function(){
if (xhr.readyState == 4){
self._onComplete(id, xhr);
}
else if (xhr.readyState == 2 ){
// Headers received
}
else if (xhr.readyState == 1 ){
// xhr.open() called
// You can set headers here amoung other things
xhr.send(data)
self._onSend( id, xhr );
}
};
xhr.open(method, url, async, user, password)
http://www.w3.org/TR/XMLHttpRequest/#the-open-method

Categories

Resources