Node js socket connection Https server amazon EC2 - node.js

I was tried socket connection in AWS EC2 with ssl certified.
i have created key file and also cert file, and attach my key into amazon load balance.
My server side code is
const socket = require( 'socket.io' );
const express = require( 'express' );
const https = require( 'https' );
const fs = require("fs");
var port = 8443;
var options = {
key: fs.readFileSync('/var/www/html/key/my.key').toString(),
cert: fs.readFileSync('/var/www/html/key/my.crt').toString(),
NPNProtocols: ['http/2.0', 'spdy', 'http/1.1', 'http/1.0']
};
var app = express();
var server = https.createServer(options , app);
var io = require('socket.io')(server);
io.sockets.on( 'connection', function( client ) {
console.log( "New client !" );
client.on( 'search_id', function( data ) {
console.log( 'Message received ' + data.search_id );
io.sockets.emit( 'search_id', { search_id: data.search_id } );
});
});
server.listen(8443, function () {
var addr = server.address();
console.log(' server listening on :' + addr.port);
});
My Client side code is
<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/1.7.3/socket.io.js"></script>
var socket = io.connect( 'https://'+window.location.hostname+':8443' );
socket.emit( 'search_id', { search_id: search_id } );
socket.on('connect_error', function(data){
console.log(data);
console.log("Connection Failed");
});
socket.on( 'search_id', function( data ) {
console.log(data);
});
I run my server js in terminal. Initialy returns server listening
Then it goes to connect_error - Connection Failed returns in my console.
My code working in my local system. What mistake i did, Is there any other configuration in AWS server?.

Related

Express and Websocket to run on the same port on the same file

I'm running two apps that sends real-time messages to each other using websocket and also generate a random link using express.js, now i hosted the server with both react apps to my vps host and want to make the websocket connection secure (wss://) but i realize i'll have to get the express server on the same port too, so the ssl/tsl works for both - so how do i do that?
Here is my full code, all on the same file:
const webSocketServerPort = 8000;
const webSocketServer = require('websocket').server;
const http = require('http');
const server = http.createServer(); server.listen(webSocketServerPort); console.log('Listening on port 8000');
const wsServer = new webSocketServer({ httpServer: server })
//GEERTOOOO
const express = require('express'); const cors = require('cors'); const fs = require('fs'); const app = express();
app.use(cors({ origin: '*' }));
app.get('/', (req, res) => { // Generate a random 6-character string const linkId = Math.random().toString(36).substr(2, 6);
// Save the link in the lex.json file fs.readFile('lex.json', (err, data) => { if (err) { console.error(err); res.status(500).send('Error generating link'); return; }
const links = JSON.parse(data);
links[linkId] = {
destination: 'http://localhost:4000/',
expires: Date.now() + 1000 * 60 * 5 // expires in 5 minutes
};
fs.writeFile('lex.json', JSON.stringify(links), (err) => {
if (err) {
console.error(err);
res.status(500).send('Error generating link');
return;
}
// Send the link back to the client
res.send(`http://localhost:3000/${linkId}`);
});
}); });
app.get('/:linkId', (req, res) => {
fs.readFile('lex.json', (err, data) => {
if (err) { console.error(err); res.status(500).send('Error retrieving link');
return;
}
const links = JSON.parse(data);
const link = links[req.params.linkId];
if (!link) {
res.status(404).send('Link not found');
return;
}
// Check if the link has expired
if (link.expires < Date.now()) {
res.status(410).send('Link has expired');
return;
}
// Redirect to the destination
res.redirect(link.destination);
}); });
app.listen(3000, () => { console.log('Server listening on port 3000'); });
//GEERTOOOO
const clients = {};
const getUniqueID = () => { const s4 = () => Math.floor((1 + Math.random()) * 0x10000).toString(16).substring(1);
return s4() + s4() + '-' + s4(); }
wsServer.on('request', (request) => { var userID = getUniqueID();
const connection = request.accept(null, request.origin); clients[userID] = connection;
connection.on('message', (message) => {
if (message.type === 'utf8') {
for(var key in clients) {
if (clients[key] !== clients[userID]) {
clients[key].sendUTF(message.utf8Data);
console.log(`Sent Message to: ${clients[key]}`);
}
}
}
}) })
Note: the express server is on port 3000 and the websocket server runs on port 8000.
I,ve tried just changing the port to same thing but i get an error when trying to use the websocket server for messages.
THE PURPOSE OF ALL THIS IS JUST TO MAKE THE WEBSOCKET CONNECTION AND EXPRESS CONNECCTION SECURE SO MY APPS (with letsencrypt ssl) can connect to the servers
It is not possible to create two separate server instances, both listening on the same port. But, specifically for a webSocket, you can share one server instance between Express and the webSocket server code. This is possible because a webSocket connection always starts with an http request (thus it can be listened for using your Express http server. And, because these http requests that initiate a webSocket all contain identifying headers they can be separated out from the regular http requests for Express by looking at the headers. The webSocket server code already knows how to do that for you.
To do that, first capture the Express server instance:
const server = app.listen(3000, () => { console.log('Server listening on port 3000'); });
Then, use that server instance when you create your webSocket server.
const wsServer = new webSocketServer({ httpServer: server });
Then, remove this code because you don't want to create yet another http server instance for the webSocket server:
const server = http.createServer();
server.listen(webSocketServerPort);
console.log('Listening on port 8000');

socketio failed: WebSocket is closed before the connection is established on production

I created an node app for websocket type project. There are no issues in my local machine, everything is working, e.g. connecting, sending and receiving but when upload to server, client is not connecting at all, it returns
WebSocket is closed before the connection is established.
below is my server code
require('dotenv').config();
const path = require('path');
const fs = require('fs');
const options = {
key: fs.readFileSync(path.join(__dirname,'../'+process.env.SSL_KEY)),
cert: fs.readFileSync(path.join(__dirname,'../'+process.env.SSL_CRT)),
ca: process.env.SSL_CA
};
const http = require('https').createServer(options);
const io = require('socket.io')(http,{
cors : {
origin : '*'
}
});
// middleware
io.use((socket, next) => {
let token = socket.handshake.query.token;
if( token == process.env.TOKEN ){
return next();
}
return next(new Error('authentication error'));
});
http.listen(3800, () => {
console.log('listening on *:3700');
});
and below is the client
<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/3.0.4/socket.io.js" integrity="sha512-aMGMvNYu8Ue4G+fHa359jcPb1u+ytAF+P2SCb+PxrjCdO3n3ZTxJ30zuH39rimUggmTwmh2u7wvQsDTHESnmfQ==" crossorigin="anonymous"></script>
<script>
var socket = io('mydomain.com:3800?token=myapp2021',{
transports : ['websocket'],
secure : true
});
socket.on('connect', function() {
console.log( socket.connected );
});
</script>
Any help, ideas, suggestions, are greatly appreciated.
Did you allow incoming TCP connections at port 3800 on your server? Seems like firewall is blocking connections.

Node Socketio Websocket on Subdomain

Since weeks I am trying to implement my websocket functionality on my production (ubuntu) Server (nginx). My websockets work locally, but I Keep getting Errors on production.
My socket.js Looks like this:
var fs = require('fs');
var options = {
type: "local",
key: fs.readFileSync("/etc/nginx/ssl/sub.domain.com/467605/server.key"),
cert: fs.readFileSync("/etc/nginx/ssl/sub.domain.com/467605/server.crt")
};
if (options.type == 'dev') {
var app = require('http').createServer(handler);
} else {
var app = require('http').createServer(options,handler);
}
var io = require('socket.io')(app);
var Redis = require('ioredis');
var redis = new Redis();
function handler(req, res) {
res.writeHead(200);
res.end('');
}
io.on('connection', function(socket) {});
// Redis UserSignedUp Channel, Channel if user signs up
var redisUserSignedUp = new Redis();
redisUserSignedUp.subscribe('signed-up-channel');
redisUserSignedUp.on('message', function(channel, message) {
message = JSON.parse(message);
io.emit(channel + ':' + message.event, message.data);
});
// run server on port 3333
app.listen(3333, function () {
console.log('Server running!');
});
My Event.js Looks like this:
const socket = io('sub.domain.com:3333', {
secure: true
});
// ... works locally
socket.on('signed-in-channel:App\\Events\\UserSignedIn', (data) => {
this.signedInUsers = data.username;
this.$toasted.info('Success: ' + data.username, {
theme: "primary",
duration: 10000
});
});
If I do this in my Event.js:
const socket = io('sub.domain.com:3333', { secure: true });
I get this error:
https://sub.domain.com:3000/socket.io/?EIO=3&transport=polling&t=MdZoLnn
net::ERR_SSL_PROTOCOL_ERROR
Where as if I watch for the Server ip like this:
const socket = io('123.123.123.123:3333', { secure: true });
I get this error:
https://123.123.123.123:3333/socket.io/?EIO=3&transport=polling&t=MdZpRnE
net::ERR_CONNECTION_TIMED_OUT
The site has an let's encrypt ssl certificate, further the webserver is nginx and the os is ubuntu. On my local window (wamp) it works starting it with node socket.js.

Nodejs socket io connect error ERR_CERT_AUTHORITY_INVALID

My error isindex.js:83 WebSocket connection to 'wss://54.38.211.175:3000/socket.io/?EIO=3&transport=websocket' failed: Error in connection establishment: net::ERR_CERT_AUTHORITY_INVALID
Server codes
var fs = require('fs');
var options = {
key: fs.readFileSync('privateKey.key'),
cert: fs.readFileSync('certificate.crt')};
var app = require('https').createServer(options);
var io = require('socket.io')(app);
io.on('connection', function(socket) {
socket.emit('on_test', {'x': 1});
});
app.listen(3000);
Client codes
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.1.1/socket.io.js"></script>
<script>var HOST = "https://54.38.211.175:3000"; // PUT YOUR VPS IP THERE
var SOCKET = null;
if (!SOCKET) {
SOCKET = io.connect(HOST, {rejectUnauthorized: false ,secure: true,transports: ['websocket']});
SOCKET["on"]("connect", function (b) {
console["log"]("baglandim");
});
SOCKET["on"]("connect_error", function (a) {
console.error("eror =" + a);
});
console.log(SOCKET);
}</script>
i create ssl but its doesnt work.my site works with SSL so I'm not connecting to socketio with http
i solve .
the certificate of the website connected to the socketio nodejs must be read.
for plesk
var fs = require("fs");
var options = {
key: fs.readFileSync(
"/usr/local/psa/var/modules/letsencrypt/etc/live/YOURSITE/privkey.pem"
),
cert: fs.readFileSync(
"/usr/local/psa/var/modules/letsencrypt/etc/live/YOURSITE/fullchain.pem"
)
};
var app = require("https").createServer(options);
var io = require("socket.io").listen(app);
app.listen(2083);
//app.listen(PORT);
console.log('acigim');

Node js, Call WebSocket server from http server

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.

Resources