I'm new to node.js and socket.io (latest versions).
I can't find any good enough documentation about handshaking with socket.io 1.0. I know modules exists, but for the sake of understanding socket.io and node.js, I don't want to add other third party modules (like express).
My code work if I accept the handshake, but if I do as said in the socket.io documentation for the error handling, I don't know how to handle that client side. With the developers tools from Chrome, I can see the error in the Network panel from the server to the client, but I can't figure how to get this value in said client and act accordingly.
Here the piece of code that give me headaches :
io.use(function(socket, next) {
// some checks
if (true) {
next(); // this work
} else {
next(new Error('Authentication error'));
}
}
Maybe I should remove this next(new Error('...')) and just disconnect the socket server side, return something else ?
Or maybe I need to add a parameter somewhere (I also want to stay in websocket mode, not polling) server or client side ?
Thanks !
Ok, just found what I'm missing, I just need to add socket.on('error', function ()); client side to catch the error.
Related
In Node.js, I have implemented a WebSocket server which is used by a smartphone app. In some cases I got this kind of error (Invalid WebSocket frame: RSV1 must be clear):
This kind of application is running on many different servers across the world, but have the problem only with one instance. The app crashes randomly when using the communication between smartphones (Android or IOS) but it did not crash if I try to send messages over WebSocket using Java.
Looking at the doc of WebSocket specification have found that:
Currently, I can't find what could be wrong. Do you think it could be some "network set-up issue"?
The libraries used for WebSocket in Node.js is ws 6.2.1.
The service is running inside a docker using alpine:8 image. As I told I have a problem only in one environment in all other environments everything works fine. Any idea what else to check?
Well in my case i was sending an object, when i JSON.stringify() it , it started working
For my case I put in return and it solves my issue:
Before:
if (pathname === "/foo/1") {
wss.handleUpgrade(request, socket, head, function done(ws) {
wss.emit("connection", ws, request);
});
}
After:
if (pathname === "/foo/1") {
wss.handleUpgrade(request, socket, head, function done(ws) {
wss.emit("connection", ws, request);
});
return;
}
I think the RSV1 bit can be related to compression setting. There is a similar question to yours ("Invalid WebSocket frame: RSV1 must be clear) here: "Error: Invalid WebSocket frame: RSV1 must be clear" while using Socket.IO
All you need to do is on the server side, pass on an option related to the
"Sec-WebSocket-Extensions: permessage-deflate;"
,
for example,
new Server({
perMessageDeflate {
...
}
});
I would love to know a few things about Node.js async and MongoDB.
If the server starts before my connection to, and my templates or Ajax depend on data from the database will serving (I precompile my handlebars) the HTML file fail or will my templates/Ajax wait for the connection and then continue?
If it works, I would love to understand better how exactly it worked!
If it fails, how can I "fix" it elegantly?
This is an example of a solution, using hoisting (seems bad to me tbh):
//connect to db
mongodb.connect("someDBplace",
(err, db)=>{
if(err){
return generalLogger.error(`The database has failed to connect: ${err}.`);
}else{ //start the server now:
generalLogger.info(`Connected to database: ${stringify(db.databaseName)}.`);
server.listen(`${port}`, (err)=>{
if(err){
generalLogger.error(err);
}
//for demo: console th eMIMEtype
generalLogger.info(`The Server started on port: ${port}.`);
});
}
});
Yes, this is a correct way to do it. If you want to make sure that the database is available before the server starts serving requests, then you need to start the server in the callback of the database connection method.
Some higher level frameworks like Hapi may provide you some mechanisms to simplify the case when you need to wait for several things before starting. For example see the Hapi plugins:
https://hapijs.com/tutorials/plugins
I'm making a remote debugging tool for Unity(C#), and I've set up a C# WebSocket server in the game that emits Log messages.
The remote debugging client is in JavaScript, on a page served by an http server also created by the game.
I seem to be running into issues sending messages on some browsers, and I'm not sure why. I am running the websocket server on localhost and running the client locally, and I know that kind of stuff is not really liked by chrome/firefox. But the weird thing is that I'm not getting any hard errors or exceptions. Failures seem to fail silently.
I'm pretty certain that the issue is JS/Browser related as the C# websocket server works and receives connections in all cases.
Anyway, here's the socket part of the JS code:
var socket = null;
var host = "ws://"+window.location.hostname;
var port = 55000;
var url = host+":"+port+"/msg";
function CheckSocketStatus()
{
if(socket!=null){
console.log(socket.readyState);
}
}
function CreateSocket()
{
socket = new WebSocket(url);
socket.onopen = function()
{
// // Web Socket is connected, send data using send()
console.log("Socket Open!");
socket.send("Here's a client message for ya!");
};
socket.onmessage = function (evt)
{
var message = evt.data;
console.log("MSG: " + message);
var obj = JSON.parse(message);
console.log(obj)
console.log(obj.type)
if(obj.type == "log"){
console.log("Recieved Log");
handleLogMessage(obj);
}
};
socket.onerror = function()
{
console.log("Error!");
}
socket.onclose = function(event)
{
// websocket is closed.
console.log(event.code);
console.log("Connection is closed...");
socket = null;
};
}
In all cases, when I call CreateSocket() a socket gets created and successfully connects to the server. I also have that CheckSocketStatus() function which returns "1" after the socket opens (Which should mean open/ready to send/receive). After that, here are the results:
Chrome:
Chrome will immediately close after connecting. The only thing I do in the onopen() function is a console.log() and a send(). If I remove the send() then the socket will stay open. I do not receive any messages from the server.
Firefox:
Firefox will keep the socket open indefinitely even if I call the send() function in onopen(). However, the server does not receive any messages from the client and vice versa. I feel like I managed to it to send client->server earlier but I could not reproduce that while testing for this question.
Microsoft Edge:
Weirdly enough, Edge works just fine. I can receive and send messages. Works exactly as intended.
Node Webkit (nw.js):
I'm also trying to write this as a nw.js app. Predictably, as it's running on chromium (or something googly), it produces the same results as Chrome.
So I'm not really sure what's going on. I'm not really a web programmer so intricate http stuff is not really my forte. I'm really hoping it's just a Local file issue with chrome/firefox and that it'll work fine on those platforms if I'm connecting to an external host. I'll try to test this tomorrow at work with some non-localhost server, and I'll update with my findings.
I guess the answer I'm looking for is what these symptoms point to and how I can get chrome/firefox/webkit to work properly.
Also what does Edge do here that the others do not?
Thanks in advance! If you need any more info from me please just ask! I didn't want to overload this question just in case there's a simple answer.
Update:
So I just tried connecting from my laptop to my desktop and the same issues still persist. So to my surprise it's not a local issue. I'm a bit stumped. I might have to look at the server code as well. I've also been told to try to use a wrapper, like socket.io, that might solve some platform dependent issues.I've worked with Socket.io/Unity before but I don't think I was having these issues (I wasn't running a server on the C# side that time, there don't seem to be any good socket.io server implementations on C#, and I'm not sure if socket.io interfaces with normal websockets). So that might point to a problem with my implementation on the C# side.
So I figured it out, thanks to gman. I looked at some of his code and noticed that he used a setting in his WebSocketBehavior class called "Ignore Extensions".
The websocket-sharp documentation has this to say:
"If it's set to true, the service will not return the Sec-WebSocket-Extensions header in its handshake response."
"I think this is useful when you get something error in connecting the server and exclude the extensions as a cause of the error."
So I guess that that header did not jive well with Chrome/Firefox. I'm still doing some testing but this solved the behavior I was seeing with those browsers.
So if you get similar errors, do that!
Our product is going to live soon, and some of the users are testing on it. Sometimes, they got the exception randomly and currently, the only way for me to know about it is ssh to the server and scan thousand lines of log in order to know the exception.
In my 8 hours working stack (Java, Spring, ...), I can configure the exception through Aspect, Interceptor in order to watch the exception and notify about the exception through email (sending log file, exception reason to me).
How can I do that in Meteor ? What is the error handling strategy ? Is there any thing that close to Interceptor/Aspect in Meteor so I can inject the email sending during the exception ? I don't really want to use any external service to watch our app for the performance / exception
Some packages look promising. Winston with the email transport kinda suit my needs. I will update this answer if I come up successfully with that
You can configure Email alerts for exception handling.
Add package called email using meteor add email
use callback method
Meteor.call('methodname', function (err, data) {
if (!err) {
//perform some action
}
} else {
console.log(err);
Meteor.call('sendEmail',"error in this method");
//here sendEmail methods send email about the error
}
});
I'm trying to allow access to socket.io only if the website the connection is coming from is one of the whitelisted subdomains on my server. The best would be if I could check the origin subdomain everytime a client connects to my socket.io server. I tried finding out how to do it, but haven't found a good solution yet.
The only thing that comes close to a solution is this answer to a related question. However - I'm not sure if that's the best way to do it and if that even works in my case and can't be faked via javascript.
TLDR: How do I treat socket.io requests differently based on their origin? If that's not possible: How do I host two socket.io servers on two subdomains, but same port?
Regarding duplicate flag: My Question is entirely different. I cannot use namespaces as a solution since I can't trust the client side javascript running on some subdomains. Therefore these subdomains could just join a different namespace, which would make my efforts to separate them pointless.
I found this answer with the help of some guy on the socket.io slack server.
io.on('connection', function (socket) {
var subdomain = socket.handshake.headers.host.split('.')[0];
if (subdomain === 'allowed') {
socket.on('login', /* ... */);
} else {
socket.on('login', function () {
console.log('login disabled, wrong subdomain');
});
}
}
I don't know it it's reliable or can be modified by malicious client javascript, but it was looking quite good while I was testing it.
I added the this modifie code to the express/socket.io middleware function so it gets called on every request: connect, disconnect, and streaming.
I also use the express-subdomain npm
https://www.npmjs.com/package/express-subdomain
app.sio.use((socket, next) => {
var subdomain = socket.request.headers.host
sessionMiddleware(socket.request, {}, next)
})