try catch doesn't work with sse - javascript

This is the code, P.S: the service httpd in s10 is stopped
try {
var source = new EventSource("http://s10/server.php");
console.log(source);
} catch (e) {
console.log("ADSfasfasfasdfasdfas" + e)
}
this is the console:
why the heck the try catch is not catching the error ??
ofcourse I have onerror event and onclose event:
source.addEventListener('error', function(e) {
if (source.readyState == 2) {
connectionClosed();//to change some style
console.log("Disconnected");
}
}, false);
source.onerror = function(e) {
if (source.readyState != 0) {
connectionClosed();//to change some style
console.log("Disconnected");
}
};
source.onclose = function() {
connectionClosed();//to change some style
console.log('Connection closed');
}

When I run this in the Console on an arbitrary URL that isn't set up to handle SourceEvents, the Console successfully logs a SourceEvent instance. This is similar to what you're describing.
So my guess here is that there's no error to catch. The SourceEvent instance is successfully constructed, even though there's no actual connection. If you want to detect if the connection is working, use the EventSource.readyState property.
In my screenshot you can see that readyState = 0, which means that the connection is "connecting", but in reality it's never going to finish connecting because the server on the other side isn't set up to handle SourceEvents.
https://developer.mozilla.org/en-US/docs/Web/API/EventSource/readyState

I'm testing the same thing, the onerror doesn't provide really useful info. For example, if you shut down your server or if you send an empty response while your client is connected, you can't detect programmatically on the client side the specific cause, I can see that just inspecting the dev console.

Related

Socket.io stops working after multiple refreshes

I have a socket.io connected to a https server listening for javascript to emit information to it. I am finding that when I refresh, the socket is recording the connection - so if i console.log something in the on('connection', function(socket) { } part of the code, I will see a response in the console.
What I am finding though, is that on the server side, the socket.on() calls are not picking up anything.
So if I have a line in Javascript which is socket.emit('ping', msg), 'ping' will work on the server side for the first 9-10 refreshes, and then on the 11th refresh it will stop working - and it will stop working on all devices and all browsers. So if I open another browser and try to load it up, it won't work either.
I have checked to see if there are multiple connections building up or something like that, but I am not seeing anything. Any idea why this weird behaviour is happening?
Server Side
io.use(function(socket, next) {
// Authentication of the user is happening here - checking for cookies, sessions, etc.
}).on('connection', function(socket) {
// Setting up some variables and checking other stuff
var socketID = socket["id"];
var username = socketUsers[socketID];
locked[socketID] = {};
// Checking for the username
if(username == '' || typeof username == "undefined") {
// Emit some stuff back to Javascript
io.to(`${socketID}`).emit('criticalError', true);
return false;
}
else {
// We have a valid login, so connect to the server
++connected;
// This line will console log every time I refresh
console.log("Some text");
socket.on('ping', function(msg) {
// This line will console log for the first 9-10 refreshes, and then it suddenly stops working. Any ideas why?
console.log('Server was pinged by ' + username);
});
// This line will console log every time I refresh
console.log("Some other text");
}
});
Client side
var socket = io('https://example.com:1337');
$(document).ready(function() {
socket.emit('ping', true);
});
This is an interesting problem that you are facing. There are multiple points to check on - However the first problem I would suggest is with the below code:
var socket = io('https://example.com:1337');
$(document).ready(function() {
socket.emit('ping', true);
});
If this is the exact code on the client side, chances are that the socket.emit is getting called before the connection handshake goes through. This can be random as sometimes the document ready event might be delayed. Try setting a timeout for the emit event -
var socket = io('https://example.com:1337');
$(document).ready(function() {
setTimeout(function(){socket.emit('ping', true);},2000);
});
and give it a try. If this works, you found the problem. Next step is to ensure authentication is working correctly - Without the complete code, advising on this is difficult. Feel free to edit the question and share the code if your issue isn't resolved.

Inspecting multiple WebSocket connections at the same time

I am using solutions provided in following topics to inspect WebSockets traffic (messages) on the web page, which I do not own (solely for learning purposes):
Inspecting WebSocket frames in an undetectable way
Listening to a WebSocket connection through prototypes
https://gist.github.com/maskit/2252422
Like this:
(function(){
var ws = window.WebSocket;
window.WebSocket = function (a, b, c) {
var that = c ? new ws(a, b, c) : b ? new ws(a, b) : new ws(a);
that.addEventListener('open', console.info.bind(console, 'socket open'));
that.addEventListener('close', console.info.bind(console, 'socket close'));
that.addEventListener('message', console.info.bind(console, 'socket msg'));
return that;
};
window.WebSocket.prototype=ws.prototype;
}());
The issue with the provided solutions is that they are listening on only 1 of 3 WebSocket connections ("wss://..."). I am able to see in the console the messages that I receive or send, but only for one connection.. Is there something I am missing? Is it possible that two other service are any different and prohibiting the use of prototype extension technique?
p.s. I will not provide an URL to the web resource that I am doing my tests on, in order to avoid possible bans or legal questions.
Okay, since it's been weeks and no answers, then I will post a solution which I ended up using.
I have built my own Chrome extension that listens to WebSocket connections and forwards all requests and responses to my own WebSocket server (which I happen to run in C#).
There are some limitations to this approach. You are not seeing the request header or who is sending the packets.. You are only able to see the payload and that is it. Also you are not able to modify the contents in any way or send your own requests (remember - you have no access to header metadata). Naturally, another limitation is that you have to be running Chrome (devtools APIs are used)..
Some instructions.
Here is how you attach debugger to listen to network packets:
chrome.debugger.attach({ tabId: tabId }, "1.2", function () {
chrome.debugger.sendCommand({ tabId: tabId }, "Network.enable");
chrome.debugger.onEvent.addListener(onTabDebuggerEvent);
});
Here is how you catch them:
function onTabDebuggerEvent(debuggeeId, message, params) {
var debugeeTabId = debuggeeId.tabId;
chrome.tabs.get(debugeeTabId, function (targetTab) {
var tabUrl = targetTab.url;
if (message == "Network.webSocketFrameSent") {
}
else if (message == "Network.webSocketFrameReceived") {
var payloadData = params.response.payloadData;
var request = {
source: tabUrl,
payload: params.response.payloadData
};
websocket.send(JSON.stringify(request));
}
});
}
Here is how you create a websocket client:
var websocket = new WebSocket("ws://127.0.0.1:13529");
setTimeout(() => {
if (websocket.readyState !== 1) {
console.log("Unable to connect to a WebsocketServer.");
websocket = null;
}
else {
console.log("WebsocketConnection started", websocket);
websocket.onclose = function (evt) {
console.log("WebSocket connection got closed!");
if (evt.code == 3001) {
console.log('ws closed');
} else {
console.log('ws connection error');
}
websocket = null;
};
websocket.onerror = function (evt) {
console.log('ws normal error: ' + evt.type);
websocket = null;
};
}
}, 3000);
Creating the server is outside the scope of this question. You can use one in Node.js, C# or Java, whatever is preferable for you..
This is certainly not the most convenient approach, but unlike java-script injection method - it works in all cases.
Edit: totally forgot to mention. There seems to be another way of solving this, BUT I have not dig into that topic therefore maybe this is false info in some way. It should be possible to catch packets on a network interface level, through packet sniffing utilities. Such as Wireshark or pcap. Maybe something I will investigate further in the future :)

Sending data in a timer by JS WebRTC crashes when reloading before the end

I have this simple piece of code in a server.js javascript file served by node:
function multiStep(myConnection, data) {
var i=0;
var myTimer=setInterval(function() {
if (i<data.length){
var element=JSON.stringify(data[i]);
console.log("mando elemento: "+element);
myConnection.send(element);
i++;
}
}, 3000);
}
//require our websocket library
clearInterval(myTimer);
var WebSocketServer = require('ws').Server;
//creating a websocket server at port 9090
var wss = new WebSocketServer({port: 9090});
//when a user connects to our sever
wss.on('connection', function(connection) {
loadJSON(function(response) {
//when server gets a message from a connected user
connection.on('message', function(message){
console.log("Got message from a user:", message);
});
var json = JSON.parse(response);
multiStep(connection, json, 0);
})
});
loadJSON simply loads a json data file from another web site.
When I run the client application the first time or when the timeout has ended everything goes fine. Yet if I reload the page while the timeout is not finished I get a crash when I try to use the connection of the old page on the server with report:
/var/www/html/MATERIALI/phonegap/node_modules/ws/lib/WebSocket.js:219
else throw new Error('not opened');
^ Error: not opened
at WebSocket.send (/var/www/html/MATERIALI/phonegap/node_modules/ws/lib/WebSocket.js:219:16)
at null. (/var/www/html/MATERIALI/phonegap/WebRTC/server.js:36:9)
at wrapper [as _onTimeout] (timers.js:261:14)
at Timer.listOnTimeout [as ontimeout] (timers.js:112:15)
As a matter of fact I could simply ignore the old session given the page is reloaded. How do I avoid the server to crash in these circumstances?
Ok, I think I found the solution; function multiStep becomes:
function multiStep(myConnection, data) {
var i=0;
clearInterval(myTimer);
myTimer=setInterval(function() {
if (i<data.length){
var element=JSON.stringify(data[i]);
console.log("mando elemento: "+element);
try {
myConnection.send(element);
console.log("mandato elemento");
} catch(err) {
console.log('Websocket error: %s', err);
}
i++;
} else {
}
}, 3000);
}
And it does not crash any longer.
You need to do some checking along the way. Your code assumes that everything is 100%.
var json = JSON.parse(response);
multiStep(connection, json, 0);
You assume there is data in response (it might be empty, or contain non-json data)
You should also check that json is a valid array before passing it to multiStep
The function multiStep also assumes that data.length will return something numeric
This may not be the complete answer, but it should give you a start on making your code more robust.
It's probably failing at myConnection.send(element); but that is probably only a symptom of your lack of checking along the way (you can also check if myConnection is still valid before you send something to it)
Referring to https://developer.mozilla.org/en-US/docs/Web/API/WebSocket, you should be able to check the myConnection.readyState value:
Ready state constants
These constants are used by the readyState attribute to describe the state of the WebSocket connection.
Constant Value Description
CONNECTING 0 The connection is not yet open.
OPEN 1 The connection is open and ready to communicate.
CLOSING 2 The connection is in the process of closing.
CLOSED 3 The connection is closed or couldn't be opened.
Your code will look like this now:
console.log("mando elemento: "+element);
if (myConnection.readyState === 1)
myConnection.send(element);
else
console.log("web socket not open");

How do I catch a WebSocket connection interruption?

In Firefox (at least), if you hit ESC, then it will close all open WebSockets connections.
I need to capture that disconnection and try to re-connect once it's available again.
Here's an example of the code I've tried to implement, but nothing I can figure out will catch the error and allow me to handle it gracefully.
Have a look at the code: http://jsfiddle.net/w5aAK/
var url = "ws://echo.websocket.org";
try {
socket = window['MozWebSocket'] ? new MozWebSocket(url) : new WebSocket(url);
socket.onopen = function(){
console.log('Socket is now open.');
};
socket.onerror = function (error) {
console.error('There was an un-identified Web Socket error');
};
socket.onmessage = function (message) {
console.info("Message: %o", message.data);
};
} catch (e) {
console.error('Sorry, the web socket at "%s" is un-available', url);
}
setTimeout(function(){
socket.send("Hello World");
}, 1000);
Turn on your console and watch the output.
Am I doing something wrong here, or is it just not possible because the connection is running outside of the scope of the JS script?
Any input would be helpful.
Thanks!
You can attach a handler to the socket.onclose event. It will be called when you hit ESC and the connection is interrupted.
See: http://jsfiddle.net/w5aAK/1/
One problem that you can't get around at the moment is the interrupted error being output to the console. There's no way of capturing that at the moment I'm afraid.
You can't catch it and it's not your fault. It's FireFox bug. Vote for it here:
https://bugzilla.mozilla.org/show_bug.cgi?id=712329
I personally tried all kind of solutions:
event handlers onunload onbeforeunload onclose try..catch some js error handling 3rd party services etc.
You can log to console your socket, it's closed before unload, but FF thinks different.. :(
Solution (not answer directly to the answer, but it works):
It's a bug, so you can't catch, but this info is not Solution. After all kind of crazy workarounds and tries to catch that bug, i finally found this working. If you use socket.io to work with WebScokets it can work with different transport technologies. xhr-polling works with Firefox.
if (/Firefox[\/\s](\d+\.\d+)/.test(navigator.userAgent)) { //test for Firefox/x.x or Firefox x.x (ignoring remaining digits);
socket = io.connect('//' + node_server + '/', {
transports: ['polling']
});
} else {
socket = io.connect('//' + node_server + '/');
}
What helped me - might help you too:
Web Socket support in Node.js/Socket.io for older browser
Define transport types on the client side
socket.io doens't work with transports: [ 'xhr-polling' ]

Emit message to add-on from content script onbeforeunload?

I have a content script which times how long a user views a page. To do this, I inject a content script into each page, start a timer and then emit a message back to the add-on when the onbeforeunload event is triggered.
The message never seems to get passed to the background script however.
Given that my main.js looks like this:
var pageMod = require('page-mod'),
self = require("self");
pageMod.PageMod({
include: "http://*",
contentScriptFile: [self.data.url('jquery.min.js'),
self.data.url('content.js')],
onAttach: function(worker) {
worker.port.on('pageView', function(request) {
console.log("Request received");
});
}
});
I can send a message to main.js using the following code no problem.
self.port.emit('pageView', { visitTime: time });
I run into a problem when I try to do it as the user leaves the page however. The message is never received when I do it like this:
$(window).bind('onbeforeunload', function(e) {
self.port.emit('pageView', { visitTime: time });
// This should prevent the user from seeing a dialog.
return undefined;
});
I've tried listening for beforeunload too, that doesn't work either. What could be the problem?
The window object that content scripts access in Firefox browser add-ons is a proxy object and can be a little temperamental. Using window.addEventListener will work.
window.addEventListener('beforeunload', function(e) {
# Do stuff then return undefined so no dialog pops up.
return undefined
});
The onbeforeUnload event is not synchronous, so the browser garbage collects the page before it is finished. Use a synchronous AJAX request:
function Data()
{
var client = new XMLHttpRequest();
client.open("GET", "/request", false); // third paramater indicates sync xhr
client.setRequestHeader("Content-Type", "text/plain;charset=UTF-8");
client.send({ visitTime: time });
client.onreadystatechange = emitter;
}
function emitter()
{
self.port.emit('pageView', { visitTime: time });
}
or return a string as an alternative.

Categories