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
Related
I'm trying to get posts from my tumblr blog and put them on a separate website page. To do this I registered an app on their OAuth page, but I'm having some issues when I try to actually request the authorization. My console spits out this message—
XMLHttpRequest cannot load https://api.tumblr.com/v2/blog/myblog.tumblr.com/posts?api_key=(MY_KEY).
No 'Access-Control-Allow-Origin' header is present on the requested resource.
Origin 'http://127.0.0.1:63342' is therefore not allowed access.
(I've omitted the key value here for obvious reasons).
Now, my site isn't actually live yet, and I have a test server running at localhost:63342 but on their OAuth app settings page I have these options that I must fill out—
Is there a way to get this to work with my local test server? Here's the code that I'm calling to request access.
var request = new XMLHttpRequest();
request.open('GET', 'https://api.tumblr.com/v2/blog/myblog.tumblr.com/posts?api_key=(API_KEY)', true);
request.onload = function() {
if (request.status >= 200 && request.status < 400) {
// Success!
var data = JSON.parse(request.responseText);
console.log(data);
} else {
// We reached our target server, but it returned an error
console.log('server error');
}
};
request.onerror = function() {
// There was a connection error of some sort
console.log("ERROR!!!");
};
request.send();
Any help would be appreciated! Thanks!
Turn out my issue was using JSON instead of JSONP, which bypasses the Access-Control-Allow-Origin issue. I downloaded this JSONP library for Javascript ( I am not using JQuery in my project ) and was able to access the api by writing this:
JSONP('https://api.tumblr.com/v2/blog/myblog.tumblr.com/posts?api_key=(API_KEY)'
, function(data) {
console.log(data);
});
Which returns a JSON Object which I can then data from using something like data.response or whatever objects are in the array.
Again, my issue was not Tumblr not authorizing my test server. I was able to get this to work using 127.0.0.1:port as my application website & callback url.
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
This question already has answers here:
Cross origin requests are only supported for HTTP but it's not cross-domain
(9 answers)
Closed 7 years ago.
I have been using an HTTP request in a JS file to retrieve information from a local JSON file. It works just fine on my Windows computer in Firefox and Chrome, but when run on a Mac, the Chrome debugger throws an error saying that Cross origin requests are only supported for HTTP...
My HTTP request code is as follows:
var xhr = new XMLHttpRequest();
xhr.open("GET", "sample.json", true);
xhr.onreadystatechange = function() {
if (xhr.readyState === 4) {
var status = xhr.status;
if ((status >= 200 && status < 300) || status === 305) {
var myData = JSON.parse(xhr.responseText);
window.myData = myData;
showAll(myData);
}
}
};
xhr.send(null);
Any ideas? Thanks
Yes, this is a security issue. You need to run this on a server, and the file:/// protocol is not supported for such kind of requests! AJAX is a proper HTTP request response kind of concept and you cannot use file:/// protocol or use different protocols for the transaction.
I'm writing an iOS application using PhoneGap (aka Cordova), I have a simple html login page that logs the user in using an XMLHttpRequest with basic authentication over SSL. Everything works splendidly when you enter your username and password correctly. However, if you enter the wrong username/password none of my callbacks are ever called.
If you run the same code on Chrome for example, with the wrong username/password, chrome behaves in a similar manner, except it pops up an authentication challenge dialog. Hitting cancel on chrome's dialog returns control to my javascript code. Unfortunately, on iOS, the UIWebView wont even popup an auth dialog, it just hangs. I need a way to tell the user that they entered the wrong username or password so they can retry.
The closest thing to an answer I could find was this http://www.freelock.com/2008/06/technical-note-http-auth-with-ajax but changing the response status from the server doesn't seem like the right thing to do.
Here's basically what my request code looks like, but when a bad username or password is sent it never reaches my onload callback (in fact the onreadystatechange callback only gets called once and thats for readyState 1, aka OPEN).
var req = new XMLHttpRequest();
req.onload = function(ev) {
if (req.status == 401) {
alert("Invalid Username/Password");
document.getElementById('password').focus();
} else if (req.status == 200) {
window.location.href = some_secure_site;
} else {
// edit //
alert("Some other status");
}
}
req.onerror = function (ev) { alert('Error'); };
req.ontimeout = function(ev) { alert('Timeout'); };
req.open('GET', uri, true, userValue, passValue);
req.withCredentials = true;
req.send();
A few things became apparent to me while trying to do this on iOS. One is that iOS has a bug relating to basic auth, so if your password has certain special characters in it you'll never get a response back from your server because your server will never get an authentication challenge. That is, if you're using the username and password field in the "open" method.
My guess is they are doing something stupid like sending it via http://username:password#myorigin.com/etc when they should be using http headers and base64 encoding the creds like so
req.setRequestHeader("Authorization", "Basic " + base64(username) + ':' + base64(password));
The other thing I learned is that Basic Auth isnt very secure and is prone to a million and one problems. One of which that will annoy you is that the client will cache the username and password, which will override any new values you send via "req.open(...)". Good luck getting around that using javascript alone, you'll have to do some magic in ObjC to clear the cache.
If you have control over your server, I would suggest using token authentication. Connect over SSL and then send a POST with JSON data containing the username and password. The server could then send back JSON data with an authentication token (essentially a bunch of random characters long enough that it can't ever be guessed, a UUID works well. this is generated by the server and can only be known to the client and the server). Then store the token and the username in the keychain so the user doesnt need to enter their creds everytime they start your app.
My server will always send back a 200 response but the JSON data will contain the information needed to either retry or to store the auth token. In general... basic auth basically sucks.
try {
var req = new XMLHttpRequest();
req.onload = function(ev) {
var response = JSON.parse(this.responseText);
if (response.success === true) {
// The server will respond with a token that will allow us to login
storeCredentials(userValue, response.token);
// redirect with token
else if (req.status == 401) {
alert("Invalid Username/Password");
document.getElementById('password').focus();
} else {
alert("Some other status");
}
}
req.ontimeout = setTimeout(function(ev) { navigator.notification.alert('Timeout trying to contact the server'); }, 10000);
req.onerror = function(ev) { clearTimeout(this.ontimeout); navigator.notification.alert('Error connecting to the server during authentication.'); };
var uri = myWebOrigin + '/authenticate';
req.open('POST', uri, true);
req.setRequestHeader('Cache-Control', 'no-cache');
req.setRequestHeader('Content-Type', 'application/json');
json_data = {username : Base64.encode(userValue), password : Base64.encode(passValue)};
req.send(JSON.stringify(json_data));
} catch(error) {
navigator.notification.alert('Uh oh, an error occurred trying to login! ' + error);
return;
}
I just had the same issues with none of the callbacks being called when using iOS + PhoneGap + jQuery. If I pass incorrect credentials and use
$.ajax({
...
timeout: 5000, // Some timeout value that makes sense
...
});
then the error callback is called with {"readyState":0,"status":0,"statusText":"timeout"}. In that case you would have to guess that the real error is the HTTP 401.
Alternatively you can use
$.ajax({
...
async: false, // :-(
...
});
and your error callback will get something like {"readyState":4,"responseText":"<html>...</html>","status":401,"statusText":"Unauthorized"} back.
To solved this problem remove the header WWW-Authenticate from server response.
There is probably an other HTTP status code beside the 401 and 200 codes received! Make sure there is really no other status code received:
if (req.status == 401) {
alert("Invalid Username/Password");
document.getElementById('password').focus();
} else if (req.status == 200) {
window.location.href = some_secure_site;
} else {
alert('Unfetched status code '+req.status+' captured!');
}
I've been having the same issue - none of the callbacks on the request are being called if invalid credentials are passed in.
My guess is that internally the UIWebView is being told to prompt for credentials, but that prompt is being suppressed, leading to this bug. This is based on all the other browsers I've tried (Safari, Chrome, Firefox) not calling the callbacks in this case until after the prompt is dismissed.
Another solution (the one I'm using) would be to not use Javascript to do the authentication, and instead do it on the iOS side - you can use the code on How to display the Authentication Challenge in UIWebView? as a rough template for doing this.
I am developing a script that helps track 404 error pages (using JavaScript) at the client side. I searched for tutorials/ posts on the same but didn't find any helpful to me.
One post mentioned using curl (PHP) on the server side & redirect the user to a custom 404 page. But that doesn't address my problem (I want it at the client side).
This page mentions how to create an http object, open up a connection & detect its status in this way:
var request = makeHttpObject();
request.open("GET", "your_url", true);
request.send(null);
....
if( request.status == 404 )
print("404 error")
But over here we ourselves are making the http request & hence have access to the object. My aim is to detect any 404 page errors from the request send by the browser (due to user navigation).
Can we monitor the browser's http object for response statuses? How does Firebug's Network Analysis feature access the http headers? Can I replicate that in my script?
I have noticed that browser's Developer tool's Console gives a 404 error for missing pages as well as individual elements like images on that page.
These are the possible solutions I could imagine:
Monitor the response.status of every http request sent by the browser
Use Developer Tool's/Browser's Error Notification to track 404 errors using an "API" for extracting those error notifications of the tool (if it exists)
Thanks a lot
You mean something like this?
function returnStatus(req, status) {
//console.log(req);
if(status == 404) {
console.log("The url returned status code " + status);
}
else {
console.log("success");
}
}
function fetchStatus(address) {
var client = new XMLHttpRequest();
client.onreadystatechange = function() {
// in case of network errors this might not give reliable results
if(this.readyState == 4)
returnStatus(this, this.status);
}
client.open("HEAD", address);
client.send();
}
fetchStatus("http://yoururl.com");