nodejs-websocket detect non-websocket connection attempt - node.js

I am running a websocket service using the nodejs-websocket module.
I would like to detect and take some action when a connection attempt is made that is not using websocket protocols.
I've thought of using setTimeout(n) and clearing the timeout when conn.readystate changes from 'connecting' to 'open' or taking an action upon the timer expiring but I'm hoping that there is a more direct way.
How can I detect a non-websocket connection attempt?

The webocket protocol starts every connection with an HTTP request with a header set that "requests" an upgrade to the webSocket protocol. When both the server agrees, it responds with the upgrade and both client and server then change the protocol to the webSocket protocol.
So, a non-webSocket connection attempt will either be a plain HTTP connection or it will be just a socket connection attempt that isn't even HTTP. So, in either case, the connection will die at the HTTP server either as a 404 (an HTTP request that the web server doesn't have a response for) or as an invalid protocol (not HTTP).

Connection has an error event, so you can do Connection.on('error', function(err) .... This will mean something went wrong on the connection, but I don't believe you can do anything with the connection at that point.
One suggestion would be to use Socket.io which can party on an HTTP/Connect/Express server. It can speak HTTP(Kinda) or WebSockets. Then you could do something like:
var app = require('express')();
var server = require('http')
.Server(app);
var io = require('socket.io')(server);
server.listen(3000);
app.get('/*', function(req, res) {
res.json({
hello: 'world'
});
});
io.on('connection', function(socket) {
socket.emit('news', {
hello: 'world'
});
socket.on('my other event', function(data) {
console.log(data);
});
});
This has all the Socket.io connections under the /Socket.io/* path. Any other connection will get handled by the app.get('/*',...) call. This would only catch http requests.

Related

Tweak nodejs socket.io behavior when receving a connection upgrade request

I am using socket.io with nodejs to start a nodejs server with websocket capabilities.
Roughly the code looks like this.
var fs = require('fs'),
app = require('http').createServer(handler),
io = require('socket.io')(app);
app.listen(8999);
function handler (req, res) {
console.log("http");
res.writeHead(101);
res.end();
}
io.on('connection', function (socket) {
socket.emit("A new connection is established");
});
One problem I have, is that when the client requests GET http://localhost:8999/ with header
Connection: Upgrade
Upgrade: websocket
I noticed that the server will not use the web server handler, and instead it does something else.
How do I ensure that when it receives any http request, the http handler is invoked? Due to the inflexibility of my client, I actually do need it to return a HTTP 101 Switching Protocols for that particular request - even with those special headers.

Create web socket streams between a server and arbitrary NodeJS processes

Having a server running on localhost:5000, I want to connect to that server from another NodeJS process, via web sockets.
From my experience with web sockets, I always needed the server object to create a web socket server.
var http = require('http');
// create http server
var server = http.createServer(function(req, res) {
// serve files and responses
...
});
// Socket.io server listens to our app
var io = require('socket.io').listen(server);
// Send current time to all connected clients
function sendTime() {
io.sockets.emit('time', { time: new Date().toJSON() });
}
// Send current time every 10 secs
setInterval(sendTime, 10000);
// Emit welcome message on connection
io.sockets.on('connection', function(socket) {
socket.emit('welcome', { message: 'Welcome!' });
socket.on('i am client', console.log);
});
server.listen(3000);
This is a tiny example using socket.io. Without having access to get the server variable (since this server will be deployed some where in the cloud), how can I connect via web sockets to this server?
An ugly solution would be via HTTP requests, but that's not web sockets. I want to keep the connection open and pipe data there.
How can I do that?
You get the socket.io-client module, require() it into your other nodejs server and use that client module from your other server (which will be the client in this case) and connect from that server to this one.
Example code here: https://github.com/automattic/socket.io-client
var socket = require('socket.io-client')('http://localhost');
socket.on('connect', function(){});
socket.on('event', function(data){});
socket.on('disconnect', function(){});

support multiple protocols on single server

I have a working Express HTTP server as well as a working websocket server. I want to add the websockets application to my regular website which is run by the HTTP server, but I'm not sure I'm understanding the documentation. Can I have a server that accepts multiple protocols and how would I handle the routing in a situation like that? The npmjs documentation for socketio says:
In conjunction with Express
Starting with 3.0, express applications have become request handler functions that you pass to http or http Server instances. You need to pass the Server to socket.io, and not the express application function.
var app = require('express')();
var server = require('http').createServer(app);
var io = require('socket.io')(server);
io.on('connection', function(){ /* … */ });
server.listen(3000);
can I handle HTTP requests through app.HTTPverbHere() and websocket requests through io.on?
The socket.io documentation shows you the exact steps needed to make socket.io work with nodejs express on the same server.
So, YES, you can do this.
In fact, every webSocket connection starts with an HTTP request (which is then upgraded to the webSocket protocol) so you must have a web server running on the server that handles webSockets anyway.
socket.io simply hooks into one route on the express web server that is used to initiate all socket.io webSocket connections and handles things from there.
Here's one example taken directly from the socket.io doc:
var app = require('express').createServer();
var io = require('socket.io')(app);
app.listen(80);
app.get('/', function (req, res) {
res.sendfile(__dirname + '/index.html');
});
io.on('connection', function (socket) {
socket.emit('news', { hello: 'world' });
socket.on('my other event', function (data) {
console.log(data);
});
});

Server showing multiple client connection (net nodejs)

I am trying to make a server which listens on a internet facing port and forwards incoming http requests to an internal express server listening at another port. Following is the relevant part of the code I'm using.
var net = require('net');
var server = net.createServer();
server.listen(addr.from[3], addr.from[2], function(){
console.log('Server listening');
});
server.on('connection',function(from){
console.log('Client connected from '+ from.remoteAddress);
var to = net.createConnection({
host: addr.to[2],
port: addr.to[3]
});
from.pipe(to);
to.pipe(from);
from.on('error',function(err){
winston.error('Error at unix box'+err);
to.end();
});
to.on('error',function(err){
winston.error('Error at middleware server'+err);
from.end();
});
from.on('end',function(){
console.log('Client disconnected ');
to.end();
});
to.on('end',function(){
console.log('Middleware disconnected');
from.end();
});
});
The problem I'm encountering is that, when I open "ip:port" in the browser (which would be the internet facing port) I'm getting messages multiple "client connected from xxxxxx" msgs on the console. Can anyone help me understand why this is happening?
Whenever browser connects to a website it usually makes two requests: normal and to retrieve favicon.
Funny thing, is that the favicon request is not even displayed in browser developer tools.
To verify, you need to extract the request made, print it to server, and then observe why you get multiple requests. For that, connection might be too early, try hooking request event instead:
server.on('request', funtion(req, res) { console.log(req.url); });

Socket.io fires connect event just after the second connect

I'm using socket.io with the latest version of node.js and socket.io shows an curious behavior:
The connect event fires on client side but not on server side for the first time.
After a reload or simply loading the page again the event got fired on both - client and server - side correctly.
What's wrong (with my code?)?
// Client
var socket = io.connect(window.location.protocol + '//' + window.location.hostname, {
'sync disconnect on unload': true
});
socket.on('connect', function() {
alert("Connect");
// Do other stuff
});
-
// Server
io.sockets.on('connection', function(socket) {
console.log("connection");
io.sockets.on('connect', function(socket) {
console.log("connect");
});
});
Started the server and loaded the page:
Client fires the alert, server just logs connection. Now loading the page again, it logs both connection and connect.
Update:
It seems that just the very first connection has such issues, afterwards it works everywhere as expected. Just after every node server (re)start, that behavior appears.
Note: node itself delivers the page where the socket.io is used and that works even on the first request, so a node issue should be excluded then.
Browser is also doesn't matter, it's the same on every browser.
For Socket.IO, connection is the server-side equivalent of connect on the client side. Therefore, when you're inside the callback for the connection event, the socket has already established a connection and you don't need to listen on some other event. I'm not sure what connect on the server side is, but it is not documented and does not work.
// on the server
io.sockets.on('connection', function(socket) {
// this connection has already been established
// no other handler is required
});
// on the client
var socket = io.connect();
socket.on('connect', function() {
// the connection has been established
});

Resources