Node js, Call WebSocket server from http server - node.js

I have a node js ( supported by express js ) http application. So I had a server.js file as follows(not there complete code).
var app = require('./app/app');
var server = http.createServer(app);
server.listen(port, host);
server.on('error', onError);
server.on('listening', onListening);
I later added websocket server to there. So it is like this now.
// app server
var app = require('./app/app');
var server = http.createServer(app);
server.listen(port, host);
server.on('error', onError);
server.on('listening', onListening);
/**
* websocker Server
*/
var WebSocket = require('ws');
var wsServer = http.createServer();
var url = require('url');
var WebSocketServer = require('ws').Server;
var wss = new WebSocketServer({ server: wsServer });
var express = require('express');
var wsApp = express();
var port = 1337;
wsApp.use(function (req, res) {
res.send({ msg: 'hello' });
});
wss.on('connection', function connection(ws) {
console.log((new Date()) + ' Connection from origin ');
ws.on('message', function incoming(message) {
console.log('received: %s', message);
var json = JSON.stringify({ type:'message', data: {hello : 'hello'} });
ws.send(json);
});
var json = JSON.stringify({ type:'message', data: {hello : 'hello'} });
ws.send(json);
});
wsServer.on('request', wsApp);
wsServer.listen(port, function () { console.log('Ws server Listening on ' + wsServer.address().port); });
Now these two are working happily. What I want is on a POST call to the http server, I want to trigger the web socket server to broadcast something to all clients. My problem is How I can trigger websocket server from http server?
Routes of http server is defined in app.js file. from there how can I call websocker server function?

If you encapsulate your ws functionality in one single javascript file (e.g: websocket.js) you could export your websocket object as a module.
module.exports = wss;
and then require it in your http controller
var wss = require(websocket.js)
In this case it should be easy to use wss.send({...}) wherever you like.

This peace of code is working to me:
//websocket.js
'use strict';
var io = require('socket.io');
var callme;
function Websocket(server) {
var server = io(server);
server.on('connection', function(socket){
console.log('Do something here');
});
callme = function (val) {
//you my choose a specific cliente if you want, read the socket.io doc
server.emit('I may emit it ' + val);
console.log("Called " + val);
return 'Somebody got it';
}
}
Websocket.route = function(req, res, next) {
if(typeof callme == 'function'){
res.send(callme(req.param('t')));
}else{
res.send('Websocket server is not running');
}
};
module.exports = Websocket;
On the express app definition, I put
var Websocket = require('./websocket');
app.use('/blablabla', Websocket.route);
Then, on the server js file, which run the application, I put
var server = http.createServer(app);
var s = new Websocket(server);
This last line works like the tradicional io(server); would work.
After that, when you request the address /blablabla the route will execute your websocket method.
My solution is not in production yet, let me know if somebody got an error.

Related

uWebSockets - push events to server

I have a uWebSockets server as it seems to be a lot more performance friendly than socket.io servers.
So I have a server and its connected fine and after some trouble I got the index.html client side to connect, but now I'm not able to push events to the server from the client side. What am I doing wrong?
var WebSocketServer = require('uws').Server,
express = require('express'),
path = require('path'),
app = express(),
server = require('http').createServer(),
createEngine = require('node-twig').createEngine;
var wss = new WebSocketServer({server: server});
wss.on('connection', function (ws) {
ws.on('join', function (value) {
console.log('SOMEONE JUST JOINED');
});
ws.on('close', function () {
//console.log('stopping client interval');
clearInterval(id);
});
});
server.on('request', app);
server.listen(8080, function () {
console.log('Listening on http://localhost:8080');
});
index.html
<script>
var host = window.document.location.host.replace(/:.*/, '');
var server = new WebSocket('ws://' + host + ':8080');
server.onmessage = function (event) {
updateStats(JSON.parse(event.data));
};
server.onopen = function (event) {
server.send("Here's some text that the server is urgently awaiting!");
server.send('join');
};
function something() {
console.log('WORKED');
server.send('join');
}
</script>
You don't have an event listener setup on the server side that does receive and react on the message. Like
ws.on('message', function (msg) {
// Do something with the message received from the client
});

How to emit message from client side [node.js + socket.io]

I am trying to emit message from client side with socket.io ...
Here is my client code:
var socket = io.connect('http://localhost/');
socket.on('connect', function(data){
setStatus('connected');
socket.emit('subscribe', {channel:'update.comment'});
});
Server:
io.sockets.on('connection', function (socket) {
socket.emit('message', { text : 'Welcome!' });
socket.on('subscribe', function (data) {
socket.join(data.channel);
redisClient.subscribe(data.channel);
});
});
Also I get this error message in console:
GET
http://localhost/socket.io?EIO=3&transport=polling&t=1442169984269-1
404 (Not Found)
Full serever:
var app = require('express')();
var http = require('http').Server(app);
var redis = require('ioredis');
var io = require('socket.io')(http);
redisClient = redis.createClient();
//look for connection errors and log
redisClient.on("error", function (err) {
console.log("error event - " + redisClient.host + ":" + redisClient.port + " - " + err);
});
io.sockets.on('connection', function (socket) {
socket.emit('message', { text : 'Welcome!' });
//on subscription request joins specified room
//later messages are broadcasted on the rooms
socket.on('subscribe', function (data) {
socket.join(data.channel);
redisClient.subscribe(data.channel);
});
});
redisClient.on('ready', function(data) {
console.log('#redis ready');
});
redisClient.on("message", function(channel, message){
console.log(channel);
var resp = {'text': message, 'channel':channel};
io.sockets.in(channel).emit('message', resp);
});
http.listen(3000, function(){
console.log('Listening on Port 3000');
});
New Problem Recognized:
Your server is listening on port 3000, but you are attempting to connect on port 80. The error message http://localhost/socket.io?EIO=3&transport=polling&t=1442169984269-1 has no port number on it so that defaults to port 80.
That error message means that your server-side socket.io code is not initialized correctly and thus is not listening for the HTTP request that starts all webSocket connections so when the browser tries to connect on that URL to initiate a socket.io connection, there's nobody on the server-side listening so the web server returns a 404 error back to the browser.
If you are using Express, this is the minimal socket.io initialization to hook it into your server:
var express = require('express');
var app = express();
var server = app.listen(8081);
var io = require('socket.io').listen(server);
For a plain HTTP server, this is the minimal socket.io initialization:
var app = require('http').createServer(handler)
var io = require('socket.io')(app);
app.listen(80);
As always, if you show us the socket.io and web server initialization code you are using, we can help you better with your specific code issue.

Conditional port forwarding by hostname

I'm a newbie to node-http-proxy module.
my aim
I need to use the module provide multi-SSL for multi-subdomain.
For example;
if a user call process.localhost:1443 then I should route the call to process.localhost:2443 and
if a user call api.localhost:1443 then I should route the call to api.localhost:3443
what's happening
I wrote the below server.js codes. However when I try to call process.localhost:1443 I get the following error;
D:\Work Space\...\http-proxy\node_modules\requires-port\index.js:13
protocol = protocol.split(':')[0];
TypeError: Cannot call method 'split' of undefined
protocol seems as undefined.
function required(port, protocol) {
protocol = protocol.split(':')[0];
What should I do?
server.js
var fs = require('fs'),
httpProxy = require('http-proxy'),
express = require('express'),
app = require('./app').service,
api = require('./api').service;
// PROXY
var options = {
changeOrigin: true,
forward: {
'process.localhost': 'process.localhost:2443',
'api.localhost' : 'api.localhost:3443'
}
}
httpProxy.createServer(options).listen(1443, function() {
console.log('Proxy is listening on port 1443')
})
// HTTP
app
.listen(2443, function() {
console.log('PROCESS APP server is listening on port 2443')
})
api
.listen(3443, function() {
console.log('API APP server is listening on port 3443')
})
I could solve this issue through someone from node-http-proxy forum.
var proxyTable = {}
proxyTable['api.localhost:1443'] = 'http://127.0.0.1:3443'
proxyTable['process.localhost:1443'] = 'http://127.0.0.1:2443'
var proxy = httpProxy.createServer({changeOrigin: true})
var http = require('http')
http.createServer(function(req, res) {
var options = {
target: proxyTable[req.headers.host]
}
proxy.web(req, res, options)
}).listen(1443, function() {
console.log('Proxy server is listening on port 1443')
})
app.listen(2443, function() {
console.log('APP server is listening on port 2443')
})
api.listen(3443, function() {
console.log('API server is listening on port 3443')
})

How to connect Two Socket.io Node Application using Socket.io-client in Node js

In my application i need to connect two socket.io node applications.Using socket.io-client we can do like this.But i don't know how socket.io-client works and where to include that.
First Node Application
var express = require('express')
, http = require('http');
var app = express();
app.use(function (req, res) {
app.use(express.static(__dirname + '/public'));
});
var server = http.createServer(app);
var io = require('socket.io').listen(server);
server.listen(3000);
io.sockets.on('connection',function(socket){
socket.on('eventFiredInClient',function(data){
socket.emit('secondNodeAppln',data);// i need to get this event in my 2nd node application how can i do this by using socket.io-client
});
});
Second Node Application
var express=require('express');
var http=require('http');
var app=express();
app.configure(function(){
app.use(express.static(__dirname + '/public'));
});
var server = http.createServer(app);
var serverAddress = '127.0.0.1';
var serverPort = 3000; //first node appln port
var clientio = require('socket.io-client');
var socket = clientio.connect(serverAddress , { port: serverPort });
socket.on('connect', function(){
console.log('connected');
});
socket.on('disconnect', function(){
console.log('disconnected');
});
var io = require('socket.io').listen(server);
server.listen(6509);
//here i need to get the 'secondNodeAppln' event raised in first node application.How can i do this.
You need to create a socket.io client in your first app:
var io = require('socket.io').listen(server); // this is the socket.io server
var clientio = require('socket.io-client'); // this is the socket.io client
var client = clientio.connect(...); // connect to second app
io.sockets.on('connection',function(socket) {
socket.on('eventFiredInClient',function(data) {
client.emit('secondNodeAppln', data); // send it to your second app
});
});
And in your second app, just listen for those events:
io.sockets.on('connection', function (socket) {
socket.on('secondNodeAppln', function(data) {
...
});
});
There's a bit of a race condition because the code above doesn't wait for a connect event on the client socket before passing events to it.
EDIT see this gist for a standalone demo. Save the three files to a directory, start the servers:
node serverserver &
node clientserver
And open http://localhost:3012 in your browser.

socket.io nodejs client show "GET http://localhost:8888/socket.io/1/?t=1342788870007 404 (Not Found) "

the client error is :
GET http://localhost:8888/socket.io/1/?t=1342788870007 404 (Not Found)socket.io.js:1632
Socket.handshake socket.io.js:1632
Socket.connect socket.io.js:1671
Socket socket.io.js:1530
io.connect socket.io.js:91
(anonymous function)
my client js:
var socket = new io.connect("http://localhost", 8888);
socket.on("chatRoom", function(data){
$("#log").html($("#log").html() + "<br>" + data);
})
$("#chatform").submit(function (event) {
event.preventDefault();
socket.emit('chatRoom', $("#chat").val())
})
and my server is:
var express = require('../node_modules/express'),
app = express.createServer(),
io = require('../node_modules/socket.io').listen(app),
fs = require('fs');
app.use(express.bodyParser());
var port = 8888;
// get html page ok
app.get('/html/*', function (req, res) {
res.sendfile(__dirname + '/html/' + req.params[0]);
});
// chat
io.sockets.on('connection', function (socket) {
socket.on("login", function(message){
socket.emit('chatRoom', "sombody connect");
})
socket.on("chatRoom", function(data){
socket.emit('chatRoom',"from server");
})
})
app.listen(port);
who can tell me what is the wrong?
i user express+socket.io in server, and i use socket.io.js in client
both server and client are in localhost
As #ebohlman mentioned
Try using
var socket = io.connect('http://localhost:8888');
in your client js instead of
var socket = new io.connect("http://localhost", 8888);
This is your issue (in the server-side code):
app.listen(port);
You need to create a separate HTTP server instead:
...
var app = express();
var server = require('http').createServer(app);
var io = require('../node_modules/socket.io').listen(server);
...
server.listen(port);

Resources