JavaScript EventSource won't open connection after Apache basic auth - javascript

I wasn't in charge of the Apache configuration, so I'm not sure what I can provide in terms of useful conf text, but I'm fairly certain I have narrowed the problem down to the login. EventSource works flawlessly both locally on XAMPP without any login and once you refresh the page after authenticating on the production server, but that first load on the server just will not open a connection. Has anyone seen this problem before? I couldn't find anything on the internet about this after searching for the past few days.
Edit: Some code
Some of the server-side code (which mostly shouldn't be relevant):
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');
$client_stream = new RedisStream();
$client_stream->poll(1); //The loop, with sleep time as a parameter
The JavaScript:
var xhttpViewSet;
var xhttpSearch;
var view = 'tile';
var search = '';
var seed_url = '/core/seed_view.php';
var stream_url = '/core/stream.php';
var default_class = 'panel-default';
var success_class = 'panel-success';
var warning_class = 'panel-warning';
var danger_class = 'panel-danger';
function UpdateClient(c_name, c_obj) {
if ((c_element = document.getElementById(c_name)) !== null) {
c_element.classList.remove('text-muted');
c_element.classList.remove(default_class);
c_element.classList.remove(success_class);
c_element.classList.remove(warning_class);
c_element.classList.remove(danger_class);
switch (c_obj['status']) {
case 0:
c_obj['status'] = 'OK';
c_element.classList.add(success_class)
break;
case 1:
c_obj['status'] = 'Warning';
c_element.classList.add(warning_class)
break;
case 2:
c_obj['status'] = 'Critical';
c_element.classList.add(danger_class)
break;
default:
c_obj['status'] = 'Unknown';
c_element.classList.add(danger_class)
break;
}
for (i in c_obj) {
var var_nodes = c_element.getElementsByClassName(i);
if (var_nodes.length > 0) {
for (var j = var_nodes.length - 1; j >= 0; j--) {
var_nodes[j].innerHTML = c_obj[i];
}
}
}
}
}
function SetView() {
var view_url = seed_url + '?search=' + search + '&view=' + view;
xhttpViewSet.open('GET', view_url, true);
xhttpViewSet.send();
}
var main = function() {
container = document.getElementById('content');
if (new XMLHttpRequest()) {
xhttpViewSet = new XMLHttpRequest();
xhttpSearch = new XMLHttpRequest();
} else {
xhttpViewSet = new ActiveXObject('Microsoft.XMLHTTP');
xhttpSearch = new ActiveXObject('Microsoft.XMLHTTP');
}
var stream = new EventSource(stream_url);
stream.onopen = function() {
console.log('Connection opened.'); //This doesn't fire
}
stream.onmessage = function(e) {
var c_obj = JSON.parse(e.data);
UpdateClient(c_obj.name, c_obj.value);
};
xhttpViewSet.onreadystatechange = function() {
if (xhttpViewSet.readyState == 4) {
var resp = xhttpViewSet.responseText;
if (xhttpViewSet.status == 200 && resp.length > 0) {
container.innerHTML = resp;
if (view == 'list') {
$('#computer-table').DataTable({
"lengthMenu": [[25, 50, 100], [25, 50, 100]]
});
}
} else {
container.innerHTML = '<error>No computers matched your search or an error occured.</error>';
}
}
}
SetView(); //This successfully does all but make the EventSource connection, and only fails to do that on first load
document.getElementById('list-view').addEventListener('click', function() {
view = 'list';
SetView();
});
document.getElementById('tile-view').addEventListener('click', function() {
view = 'tile';
SetView();
});
document.getElementById('search').addEventListener('keyup', function() {
search = this.value.toUpperCase();
SetView();
});
document.getElementById('clear-search').addEventListener('click', function() {
document.getElementById('search').value = '';
search = '';
SetView();
});
};
window.onload = main;

It is a bit hard to know for sure without a lot more information, but based on what you have said so far, I think it is one of:
HEAD/OPTIONS: Some browsers will send a HEAD or OPTIONS http call to a server script, before they send the GET or POST. The purpose of sending OPTIONS is to ask what headers are allowed to be sent. It is possible this is happening as part of the login process; that might explain why it works when you reload. See chapter 9 of Data Push Apps with HTML5 SSE (disclaimer: my book) for more details; basically, at the top of your SSE script you need to check the value of $_SERVER["REQUEST_METHOD"] and if it is "OPTIONS", intercept and say what headers you want to accept. I've used this one before:
header("Access-Control-Allow-Headers: Last-Event-ID,".
" Origin, X-Requested-With, Content-Type, Accept,".
" Authorization");`
CORS: The HTML page URL and the SSE page URL must have identical origins. There are detailed explanations (specific to SSE) in chapter 9 of Data Push Apps with HTML5 SSE (again), or (less specifically) at Wikipedia. If this is the problem, look into adding header("Access-Control-Allow-Origin: *"); to your SSE script.
withCredentials: There is a second parameter to the SSE constructor, and you use it like this: var stream = new EventSource(stream_url, { withCredentials: true }); It is saying it is okay to send the auth credentials. (Again, chapter 9 of the book goes into more detail - sorry for the repeated plugs!) There is a second step, over on the server-side: at the top of your PHP SSE script you need to add the following.
header("Access-Control-Allow-Origin: ".#$_SERVER["HTTP_ORIGIN"]);
header("Access-Control-Allow-Credentials: true");
PHP Sessions locking: This normally causes the opposite problem, which is that the SSE script has locked the PHP session, so no other PHP scripts work. See https://stackoverflow.com/a/30878764/841830 for how to handle it. (It is a good idea to do this anyway, even if it isn't your problem.)

Related

How can I get Text from Js to Python

<script>
function voice(){
var recognition = new webkitSpeechRecognition();
recognition.lang = "en-GB";
recognition.onresult = function(event){
console.log(event);
document.getElementById("speechto").value = event.results[0][0].transcript;
}
recognition.start();
}
</script>
I am making language translator web-app. And in above code, it takes input from the user using mic and print that in textarea in eng language. So I want this text in my python so that I can translate it and print it on another textarea. But i dont know how can I get that text from the js into my python code.
any soln?
Where is "your python"? I'm assuming this is on a browser over a network. You gotta set up a webserver (in python) to listen to network responses. Try webpy for a simple solution: https://webpy.org/.
You'll have to set up a URL endpoint to respond to POST requests. More info here: https://webpy.org/docs/0.3/tutorial#getpost.
And lastly, you'll have to set up your Javascript to send the post request and to use the response from your server to edit the textarea. You can use the JS fetch API to send the post request and handle the response from there.
Good luck hooking everything up
I assume you're using flask as that is tagged in your question. You need to establish a route to execute your python code and run your flask app which should listen to some TCP port on your computer (by default flask seems to use port 5000).
Then on your js code you can use the fetch method to send the text to that port. For example:
fetch('http://locahost:5000/{your flask route goes here}', {
method: 'POST',
headers: {
'Content-Type': 'text/plain',
},
body: {text you want to send goes here},
})
rather than using python just to do a translation, why not to use a simple javascript translate function?
var translate = async (t,src,dst) => {
var tt = new Promise(function(resolve) {
var i=0, len=0, r='', tt='';
const url = 'https://clients5.google.com/translate_a/';
var params = 'single?dj=1&dt=t&dt=sp&dt=ld&dt=bd&client=dict-chrome-ex&sl='+src+'&tl='+dst+'&q='+t;
var xmlHttp = new XMLHttpRequest();
var response;
xmlHttp.onreadystatechange = function(event) {
if (xmlHttp.readyState === 4 && xmlHttp.status === 200) {
response = JSON.parse(xmlHttp.responseText);
for (var i = 0, len = response.sentences?.length; i < len; i++) {
var r=(((response.sentences[i].trans).replace('}/g','')).replace(')/g','')).replace('\%20/g', ' ');
r=((r.replace('}','')).replace(')','')).replace('\%20/g', ' ');
tt += r;
}
if (tt.includes('}'||')'||'%20')) {
tt=((tt.replace('}/g','')).replace(')/g','')).replace('\%20/g', ' ');
}
resolve(tt);
}
}
xmlHttp.open('GET', url+params, true);
xmlHttp.send(null);
xmlHttp.onreadystatechange();
});
return await tt;
}

Getting Facebook to return User Data to Chrome Extension

I'm building a chrome extension that needs to allow user authentication through facebook. I've been following the "manual login flow" since the facebook Javascript SDK doesn't work in extensions. Thus far, I've allowed users to click a link that gets permissions and returns an access token:
index.html
Sign In with Facebook
index.js
function onFacebookLogin(){
if (localStorage.getItem('accessToken')) {
chrome.tabs.query({}, function(tabs) { // get all tabs from every window
for (var i = 0; i < tabs.length; i++) {
if (tabs[i].url.indexOf(successURL) !== -1) {
// below you get string like this: access_token=...&expires_in=...
var params = tabs[i].url.split('#')[1];
// in my extension I have used mootools method: parseQueryString. The following code is just an example ;)
var accessToken = params.split('&')[0];
accessToken = accessToken.split('=')[1];
localStorage.setItem('accessToken', accessToken);
chrome.tabs.remove(tabs[i].id);
console.log(accessToken)
userSignedIn = true
findFacebookName();
}
}
});
}
}
chrome.tabs.onUpdated.addListener(onFacebookLogin);
^ ALL OF THIS WORKS. Everytime a user "logs in" the localstorage.accessToken is updated. Then, I get to the point where I try to retrieve user data by inspecting the token through the api:
var client_token = '{MY_CLIENT_TOKEN(NOT CLIENT_ID}'
var inspectTokenUrl = 'https://graph.facebook.com/debug_token?input_token=' +
localStorage.accessToken +
'&access_token=' +
client_token
function findFacebookName(){
var xhr = new XMLHttpRequest();
xhr.open("GET", inspectTokenUrl, true);
xhr.onreadystatechange = function () {
if (xhr.readyState == 4) {
}
}
xhr.send();
}
But this returns a 190 oauth error. What am I doing wrong? What is the correct way to request the users email address using the access_token?

Phantomjs interprocess communication

I am trying to implement a solution where by using PhantomJS a web location is open evaluated and the output is saved to a file for processing. Specifically the scanning for malicious scripts. I have been able to implement the solution using PhantomJS running once. For example this works perfectly...
var system = require('system');
var page = require('webpage').create();
var lastReceived = new Date().getTime();
var requestCount = 0;
var responseCount = 0;
var requestIds = [];
var fileSystem = require('fs');
var startTime = new Date().getTime();
page.onResourceReceived = function (response) {
if(requestIds.indexOf(response.id) !== -1) {
lastReceived = new Date().getTime();
responseCount++;
requestIds[requestIds.indexOf(response.id)] = null;
}
};
page.onResourceRequested = function (request) {
if(requestIds.indexOf(request.id) === -1) {
requestIds.push(request.id);
requestCount++;
}
};
page.open('http://adserver.example.com/adserve/;ID=164857;size=300x250;setID=162909;type=iframe', function () {});
var checkComplete = function () {
// We don't allow it to take longer than 5 seconds but
// don't return until all requests are finished
if((new Date().getTime() - lastReceived > 300 && requestCount === responseCount) || new Date().getTime() - startTime > 5000) {
clearInterval(checkCompleteInterval);
console.log(page.content);
phantom.exit();
}
}
var checkCompleteInterval = setInterval(checkComplete, 1);
However, I have had immense difficulty trying to create and automated system that doesn't require PhantomJS to continually be restarted which has a fair bit of overhead.
I tried using a named pipe to read from and then attempt to open the passed url, but for some reason it will not open properly. I would love and deeply appreciate any guidance on this.
One thing to mention is that PhantomJS excels in HTTP communications. That's why for advanced features & better performance, I always use resource pooling pattern + webserver module. This module is still tagged EXPERIMENTAL, but I have always found it quite stable until now.
So, I think the best in your case it's better to communicate via HTTP than via files IO.
Here is a very basic example :
var page = require('webpage').create();
var server = require('webserver').create();
var system = require('system');
var host, port;
if (system.args.length !== 2) {
console.log('Usage: server.js <some port>');
phantom.exit(1);
} else {
port = system.args[1];
var listening = server.listen(port, function (request, response) {
var page=require('webpage').create();
page.open(request.post.target, function(status){
response.write("Hello "+page.title);
response.close();
});
});
if (!listening) {
console.log("could not create web server listening on port " + port);
phantom.exit();
}
//test only
var url = "http://localhost:" + port + "/";
console.log("SENDING REQUEST TO:");
console.log(url);
var data='target=http://stackoverflow.com/';
page.open(url,'post', data, function (status) {
if (status !== 'success') {
console.log('FAIL to load the address');
} else {
console.log("GOT REPLY FROM SERVER:");
console.log(page.content);
}
phantom.exit();
});
}

JS Facebook API Request seems to break sessions

I have a firefox extension that requests different APIs via XMLHttpRequest. However, the facebook like/share/comment count request leads to a logout in some online shops and some websites.
For example, GMX webmail has to restore the session after every click. Some online-shops seems to loose the session completeley so that there is an empty basket.
The problem only occurs with the facebook request enabled.
Request URL
http://api.facebook.com/method/fql.query?query=SELECT%20normalized_url,%20share_count,%20like_count,%20comment_count,%20click_count,%20total_count%20FROM%20link_stat%20WHERE%20url=%22www.heise.de%22&format=JSON
Javascript Code for the Request
var querystring = facebookURL + encodedUrl + facebookURLParams; // looks like the above
var mFacebookRequest = new XMLHttpRequest();
mFacebookRequest.onload = parseFacebookResponse;
mFacebookRequest.open( "GET", querystring );
// already tried without user-agent
mFacebookRequest.setRequestHeader( "User-Agent", "Mozilla/4.0 (compatible; GoogleToolbar 2.0.114-big; Windows XP 5.1)" );
parseFacebookResponse function
function parseFacebookResponse() {
var fbcount = "-";
var share_count = 0;
var like_count = 0;
var comment_count = 0;
var aDoc = mFacebookRequest.responseText;
if( aDoc == null || aDoc == -1 || aDoc.length == 0 )
{
} else {
var jsonDoc = JSON.parse( aDoc );
var temp = jsonDoc[0];
share_count = parseInt(temp['share_count']);
like_count = parseInt(temp['like_count']);
comment_count = parseInt(temp['comment_count']);
}
The code is working perfectly and the numbers are displayed. But it keeps me logging out. Any idea?!
you are making a cross domain XML HTTP request. This coupled with the possibility that the GMX website is setting an immediately expiring session cookie -- your session is killed. This is just a hypothesis.

Javascript HTTP GET html/text returning null/empty?

I am trying to get the html of a website using this code:
function catchData(req) {
console.debug("i got a reply!");
var returnXML = req.responseXML;
console.debug(returnXML);
if (!returnXML)
{
console.debug("html is bad");
return;
}
if (speed != currentSpeed)
moveToNewSpeed(speed);
currentSpeed = speed;
var error = returnXML.getElementsByTagName('message')[0].firstChild;
if (error) {
document.getElementById('errorMessage').innerHTML = error.nodeValue;
document.getElementById('errorMessage').style.visibility = 'visible';
}
else
document.getElementById('errorMessage').style.visibility = 'hidden';
}
function sendRequest(url,callback,postData) {
console.debug(url);
console.debug(postData);
var req = createXMLHTTPObject();
if (!req) return;
var method = (postData) ? "POST" : "GET";
console.debug(method);
req.open(method,url,true);
console.debug("request Opened");
req.setRequestHeader('User-Agent','XMLHTTP/1.0');
req.setRequestHeader('User-Agent','XMLHTTP/1.0');
if (postData)
{
req.setRequestHeader('Content-type','application/x-www-form-urlencoded');
console.debug("set post data");
}
req.onreadystatechange = function () {
if (req.readyState != 4)
{
console.debug("bad ready state");
return;
}
console.debug(req);
console.debug("responseText:");
console.debug(req.responseText);
callback(req);
console.debug("callback finished");
}
if (req.readyState == 4) return;
req.send(postData);
}
var XMLHttpFactories = [
function () {return new XMLHttpRequest()},
function () {return new ActiveXObject("Msxml2.XMLHTTP")},
function () {return new ActiveXObject("Msxml3.XMLHTTP")},
function () {return new ActiveXObject("Microsoft.XMLHTTP")}
];
function createXMLHTTPObject() {
var xmlhttp = false;
for (var i=0;i<XMLHttpFactories.length;i++) {
try {
xmlhttp = XMLHttpFactories[i]();
}
catch (e) {
continue;
}
break;
}
return xmlhttp;
}
When I do a wireshark grab I see the server returning the html, but req.responseText is just an empty string. Anyone know whats up?
I guess you're trying to get the HTML of a page that's on a different domain than your JavaScript. This is a cross-domain request, which isn't allowed in Javascript. This is usually seen as empty responses in your script.
The JSONP standard describes a mechanism to retrieve JSON from a different domain, but this needs to be implemented on the other site and doesn't work with HTML.
The Yahoo! Query Language (YQL) can act as a proxy. The Yahoo! server will fetch the HTML and create a JSONP response, which your script will receive. This may help you to accomplish your goal. The YQL has a lot of cool features for retrieving content from other sites, I recommend you read through the documentation to see if there's anything else you can use.
from where is the javascript being executed? Do you have a same-origin policy violation?
I ask because I have seen wierdness in these situations, where I was violating the policy but the request was still going out; just the response was empty...it doesn't make any sense that the browser would send the request, but they all handle it differently it appears...
Is there a reason why you're writing this code yourself instead of using a library such as jQuery? You'll find it much easier and they've already figured out all the associated quirks with browser interoperability, etc.

Categories