Firefox CORS issue with JSON - javascript

I'm trying to use the API from https://www.themoviedb.org/. (The key is free and can be changed easily, so I'll include it because without it, you can’t even test their functions).
Now my JavaScript is working fine in FF when it's hosted local, but not on GitHub pages.
Here is a function that doesn’t work. Error is:
NetworkError: A network error occurred.
…and it appears to happen after bhttp.send();.
function getMovieDetails() {
var reqURL = "https://api.themoviedb.org/3/movie/latest?api_key=afe4e10abbb804e2b4a4f8a3ef067ad5&language=en-US";
var bhttp = new XMLHttpRequest();
bhttp.open("GET", reqURL, false);
bhttp.setRequestHeader("Content-type", "json");
bhttp.send();
var response = JSON.parse(bhttp.responseText);
var str = JSON.stringify(response, null, 2);
return response;
}
console.log(getMovieDetails());
It works fine in Chrome. Googling appears to indicate it’s a CORS problem, but as far as I know GitHub pages supports CORS, so I don't know what I'm doing wrong.

I'm not a firefox user, so you will need to test this. But if the theory of async blocking is true this should work.
I've modified it to use a simple callback, personally I wouldn't use callbacks but would make into promises, but that's another question :)
function getMovieDetails(callback) {
var reqURL = "https://api.themoviedb.org/3/movie/latest?api_key=afe4e10abbb804e2b4a4f8a3ef067ad5&language=en-US";
var bhttp = new XMLHttpRequest();
bhttp.open("GET", reqURL, true);
bhttp.setRequestHeader("Content-type", "json");
bhttp.onload = function() {
if (bhttp.readyState === 4) {
if (bhttp.status === 200) {
callback(JSON.parse(bhttp.responseText));
} else {
console.error(bhttp.statusText);
}
}
};
bhttp.send();
}
getMovieDetails(function (movie) {
console.log(movie);
});

Alright looks like skirtle was correct, the issue was the firefox addon Privacy-Badger blocking the API. I feel pretty stupid now but at least my code is now pretty clean.

Related

What's the best way to check the connectivity in pure JavaScript?

I've a tried a lot of things to check the internet connection of the users of my app. My first researches brought me to the navigator.onLine method. It works sometimes. But sometimes it doesn't. Of course it's not new, I have seen multiples people complaining about that.
Then I tried the XHR request. It was working on every devices, whatever the internet navigator (not like the previous method). But I got some warnings from Chrome and Firefox cos it was synchronous and may slow the whole app.
So I converted my function to an asynchronous function :
function verification() {
var xhr = new XMLHttpRequest();
xhr.open("GET", "//" + window.location.hostname + "/ressources/favicon.ico?rand=" + Date.now(), true);
xhr.onload = function (e) {
if (xhr.readyState === 4 && xhr.status === 200) {
reconnection();
}
};
xhr.onerror = function (e) {
deconnexion();
};
xhr.send(null);
}
The idea is simple, I check if I can access to the favicon (with a rand to make it unique and avoid cache ressource). If the request is a success then I consider I'm connected. If not, I'm not connected. So far, it seems to work pretty well.
My question is : is it the best way to do that with pure JS ? Or should I maybe consider using fetch ? Or is there a better way I didn't find ?

listen to http requests of a Firefox tab with a plugin

Currently I am writing a plugin for Mozilla Firefox which is in need of the ability to listen to any http requests made by a tab. So I was reading the description of mdn's article about that topic, but I am not able to get it running.
I tried "The Easy Way" but I have no idea where to place this code. If I place it in the index.js of the plugin it just says "gBrowser is not defined" It would be really nice if someone could tell me how to get this running.
I also read this article, which seemed similar to my problem of using XMLHttpRequest which I could get to work. So I tried to form this into the solution from this problem but it does not work either.
Thank you very much for any help :)
EDIT: I was able to form the code from the second article into the solution that worked for XMLHttpRequest like this:
let { Cc,Ci } = require("chrome");
var activityDistributor = Cc["#mozilla.org/network/http-activity-distributor;1"].getService(Ci.nsIHttpActivityDistributor);
var httpObserver = {
observeActivity: function(aHttpChannel, aActivityType, aActivitySubtype, aTimestamp, aExtraSizeData, aExtraStringData){
if (aActivityType == nsIHttpActivityObserver.ACTIVITY_TYPE_HTTP_TRANSACTION) {
switch(aActivitySubtype) {
case nsIHttpActivityObserver.ACTIVITY_SUBTYPE_RESPONSE_HEADER:
// received response header
break;
case nsIHttpActivityObserver.ACTIVITY_SUBTYPE_RESPONSE_COMPLETE:
console.log('recieved !!!')
break;
}
}
}
};
activityDistributor.addObserver(httpObserver);
But it does not do the log output (or at least I can't find it in the browser console).
I found the solution, and it was just my fault. I named the variable wrong so the "nsIHttpActivityObserver" was not set ! So this would be the correct code:
let { Cc,Ci } = require("chrome");
var nsIHttpActivityObserver = Cc["#mozilla.org/network/http-activity-distributor;1"].getService(Ci.nsIHttpActivityDistributor);
var httpObserver = {
observeActivity: function(aHttpChannel, aActivityType, aActivitySubtype, aTimestamp, aExtraSizeData, aExtraStringData){
if (aActivityType == nsIHttpActivityObserver.ACTIVITY_TYPE_HTTP_TRANSACTION) {
switch(aActivitySubtype) {
case nsIHttpActivityObserver.ACTIVITY_SUBTYPE_RESPONSE_HEADER:
console.log('header received')
break;
case nsIHttpActivityObserver.ACTIVITY_SUBTYPE_RESPONSE_COMPLETE:
console.log('complete anwser received')
break;
}
}
}
};
nsIHttpActivityObserver.addObserver(httpObserver);

Illegal invocation with start/noteOn using Web Audio API

So basically I've tested this in Chrome and maybe the order of codes is off or whatever, trying to cover some of the functionality of HTML5 audio using "web audio" due to the range requests bug, for the making of games with looping sound effects and music...
I get an "illegal exception" error. Here's the code:
var url='example.mp3';
var a_result=new Object();
a_result.loaded=false;
a_result.evalstring='';
a_result.loop=false;
a_result.play=function(){
var asrc=a_result.source;
asrc.loop=a_result.loop;
//try{
var playfunc=asrc.start||asrc.noteOn;
playfunc(0);
//}catch(e){
/* do nothing */
//}
}
a_result.pause=function(){
var asrc=a_result.source;
try{
var stopfunc=asrc.stop||asrc.noteOff;
stopfunc(0);
}catch(e){
/* do nothing */
}
}
var asrc=actx.createBufferSource();
asrc.connect(actx.destination);
var req=new XMLHttpRequest();
req.open('GET',url,true);
req.responseType='arraybuffer';
req.onload=function(){
if(a_result.loaded==false){
asrc.buffer=actx.createBuffer(req.response,false);
a_result.source=asrc;
a_result.loaded=true;
}
var cont=a_result;
eval(cont.evalstring);
}
req.onerror = function() {
if(a_result.loaded==false){
a_result.loaded=true;
}
}
try{
req.send(null);
}catch(e){
req.onerror();
}
return a_result;
And then later on after the sound has loaded I do something like:
a_result.play();
And instead of playing it gives the error.
Here is a sound test that uses the above code with the fix suggested below, and it works in Chrome, successfully working around the range requests issue on a crappy web server. Here is another that has issues (throwing some kind of "invalid string" error at asrc.buffer=actx.createBuffer(req.response,false); in Iron and silently screwing up in Chrome).
Here is the code edited according to the suggestions:
var url='example.mp3'
var a_result=new Object();
a_result.loaded=false;
a_result.evalstring='';
a_result.loop=false;
a_result.play=function(){
var asrc=a_result.source;
asrc.loop=a_result.loop;
try{
if(asrc.start){
asrc.start(0);
}else{
asrc.noteOn(0);
}
}catch(e){
/* do nothing */
}
}
a_result.pause=function(){
var asrc=a_result.source;
try{
if(asrc.stop){
asrc.stop(0);
}else{
asrc.noteOff(0);
}
}catch(e){
/* do nothing */
}
}
var asrc=actx.createBufferSource();
asrc.connect(actx.destination);
var req=new XMLHttpRequest();
req.open('GET',url,true);
req.responseType='arraybuffer';
req.onload=function(){
actx.decodeAudioData(req.response,function(buffer){
if(buffer){
if(a_result.loaded==false){
asrc.buffer=buffer;
a_result.source=asrc;
a_result.loaded=true;
}
var cont=a_result;
eval(cont.evalstring);
}
});
}
req.onerror = function() {
if(a_result.loaded==false){
a_result.loaded=true;
}
}
try{
req.send(null);
}catch(e){
req.onerror();
}
return a_result;
It no longer appears to have a syntax error, however, it does not seem to solve the playability issues on Chrome (second test case above updated). Specifically, after a sound is stopped it does not want to play again. -- Apparently because it's in the spec. The buffer has to be applied to a new sound source every time you play.
In your new page, you're calling createBuffer(data, false) on the results of an XMLHTTPRequest. You almost certainly want to be calling decodeAudioData() on those results, instead - createBuffer doesn't have a 2-parameter version, and doesn't match the parameters you're passing even if you're trying to push arbitrary data into a buffer. It appears from a browse of your code that you're pulling down MP3 or Ogg files - you need to decode them.
The play method (either start() or noteOn()) needs to be invoked ON the buffersourcenode object, not disassociated from it. You have a few options:
1) I'd strongly recommend just including my audio context monkeypatch library (https://github.com/cwilso/AudioContext-MonkeyPatch/) and using the new (start()) syntax. no muss, no fuss.
2) You can just use an if statement instead of using playfunc to switch:
if (asrc.start)
asrc.start(0);
else
asrc.noteOn(0);
3) You can bind() the play function to the object and keep your code essentially the same:
var playfunc=asrc.start ? asrc.start.bind(asrc) || asrc.noteOn.bind(asrc);
playfunc(0);
4) You can push the playfunc() method onto the object itself (I think this will work):
asrc.playfunc=asrc.start||asrc.noteOn;
asrc.playfunc(0);

Ajax working only in IE

Can someone tell me which are the main differences, or aspects that I should look for, if the AJAX I'm using works perfectly on IE but does not work at all on Google Chrome or Firefox?
Are there some things that IE accept but the others dont? Or is there any code that I should add in order to works for all the browsers?
I dont know if this affect something, but I'm working with PYTHON!
Here is the code that all the Ajax functions use as base:
var xmlhttp;
var request = true;
function GetXmlHttpObject() {
try {
request = new XMLHttpRequest();
} catch (trymicrosoft) {
try {
request = new ActiveXObject("Msxml12.XMLHTTP");
} catch (othermicrosoft) {
try {
request = new ActiveXObject("Microsoft.XMLHTTP");
} catch (failed) {
return false; //or null
}
}
}
if (!request)
alert ("Error initializing XMLHTTPRequest!");
return request;
}
After doing this, I use a regular Javascript function which includes something like this:
var url = 'evaluacionDesempenoBD.py?cadena=' + cadena + '&comentario=' + comentario + '&idEvaluacion=' + idEvaluacion + '&seccion=' + seccion;
xmlhttp = GetXmlHttpObject();
if (!xmlhttp) {
alert ("Browser does not support HTTP Request");
return;
}
var xml = xmlhttp;
xmlhttp.open("GET",url,true);
xmlhttp.send(null);'''
I hope i made myself clear
Thanks a lot!
You probably use the ActiveX AJAX object and not the native implementation supported by all browsers.
Use new XMLHttpRequest() to create an AJAX object on browsers with native implementation.
Wikipedia has an awesome article on XMLHttpRequest with some sample code that should help you get your AJAX thingie work across all browsers.
Perhaps you might be facing a problem due to browser differences with regards to the internals of the XMLHttpRequest object, particularly how you handle readystate changes. Quirksmode has a document on this.

web workers behave differently in webkit than Firefox

I have a web application that works just fine in modern webkit-based browsers (http://montecarlo-tester.appspot.com/). Basically it uses a webworker to fetch data from a server, and then sends it back after performing some computations.
It works just fine in Chrome/Safari (no errors in console), but when I try to use it in Firefox, it doesn't. I've deduced that somehow the variable 'iterations' is not set properly in Firefox. Unfortunately, Firefox lacks a debugger (for web workers), and javascript has functional scoping, so it's really hard to pinpoint where the problem is. I've posted the javascript code for my web worker, and I was wondering if anybody could point out where I went wrong:
importScripts('/static/js/mylibs/jquery.hive.pollen-mod.js');
$(function (data) {
main();
//while(main());
close();
});
function main() {
//make an ajax call to get a param
var iterations//value will be set by server response
var key//key of the datastore object
var continueloop = true;
p.ajax.post({
url:'/getdataurl',
dataType: "json",
success: function(responseText){
if (responseText === null) {
var workermessage = {
"log":"responseText is null. Either the server has issues or we have run out of stuff to compute."
};
$.send(workermessage);
continueloop = false;
}
iterations = responseText.iterationsjob;
key = responseText.key;
}
});
if (continueloop === false) {
return false;
}
//here is where I think the problems begin. In chrome/safari, iterations = 1000.
//In Firefox however, iterations = null. As a result, everything after that does not work.
var i,x,y,z;
var count = 0;
var pi;
start = new Date();
for (i=0;i<iterations;i++) {
x = Math.random();
y = Math.random();
z = x*x+y*y;
if(z<=1.0){
count++;
}
}//end for loop
pi = count/(iterations)*4.0;
end = new Date();
result = {
"estimated_pi":pi,
"num_iter":iterations,
"duration_ms":end.valueOf()-start.valueOf(),
"key":key
};
//send results to the server
p.ajax.post({
url: "/resultshandler",
dataType:'json',
data: result,
success: function()
{
//do nothing!
}
});
$.send(result);
return true;//persists the loop
}
You're doing an async XHR, then immediately doing a loop trying to use its results. I have no idea why this possibly works in Chrome, but it's definitely racy. Have you tried passing "sync:true" in your post options?
Edit: Oh, nevermind. I see why your code works. The hive.pollen script has this wonderful bit:
sync: navigator.userAgent.toLowerCase().indexOf('safari/') != -1 ? false : true,
So it's doing a sync XHR in Chrome/Safari and an async one in everything else, by default (because it passes options.sync as the value for the async argument to XMLHttpRequest.open, which is backwards, but whatever; it does mean that you actually need to pass sync: false at the callsite to get sync behavior). And since you don't specify whether you want sync or async, you get sync in Chrome and async in Firefox.
Oh, and the script has this wonderful comment before that line:
// TODO: FIX THIS.

Categories

Resources