Heroku Deployment of NodeJS and ReactJS - node.js

I want to deploy 2 seperate projects on same Heroku machine. I have React application for frontend and nodejs server in the back.
They are connected over localhost in my machine with the following structure. In the react side, with following client structure, I can see the Connected to : localhost:5000 is printed. :
import openSocket from 'socket.io-client';
socket = openSocket("http://localhost:5000");
socket.on("connect", () => {
console.log("Connected to : http://localhost:5000");
});
Node Side is like following and Client connected is printed in my local machine:
const server = require('http').createServer();
const io = require('socket.io')(server);
server.listen(5000, function(err) {
if (err) throw err;
console.log('Server Listening on port:', 5000);
});
io.on('connection', (client) => {
console.log("Client connected!");
}
After that I deployed my projects on 2 different clusters in Heroku.
NodeJS works on https://<herokuname>.herokuapp.com/
So I wonder that to write in the openSocket method in React side in order to connect socketio connection on that domain. I tried followings but none of them worked :
https://<herokuname>.herokuapp.com:5000/socket.io/?EIO=4&transport=websocket
https://<herokuname>.herokuapp.com/socket.io/?EIO=4&transport=websocket
ws://<herokuname>.herokuapp.com:5000/socket.io/?EIO=4&transport=websocket
ws://<herokuname>.herokuapp.com/socket.io/?EIO=4&transport=websocket

You have to bind your server to a specific process.env.PORT provided to you by Heroku for web dynos.
const server = require('http').createServer();
const io = require('socket.io')(server);
const PORT = process.env.PORT || 5000;
server.listen(PORT, function(err) {
if (err) throw err;
console.log('Server Listening on port:', PORT);
});
io.on('connection', (client) => {
console.log("Client connected!");
}
Once that's working, you should be able to just hook up to the root heroku server URL from your client.
import openSocket from 'socket.io-client';
const url = "https://<herokuname>.herokuapp.com"
socket = openSocket(url);
socket.on("connect", () => {
console.log("Connected to:", url);
});
Here are some relevant docs on the subject, noting that you'll probably want session affinity turned on if you plan on using socket.io in heroku:
https://devcenter.heroku.com/articles/dynos#local-environment-variables
https://devcenter.heroku.com/articles/session-affinity

Related

Unable to connect to socket.io server over local network

I am trying to set up communication between my nodeJS server and a vueJS app via socket.io. I have been able to get the socket communication working on my main computer so far. When running my node server and my vue app in dev mode, I can open the vue app in the browser and I see the connection coming through my server.
However, when I open the vueJS app on my iPad (connected to the same wifi) the vue app loads and runs fine but my socket connection never goes through. I am also unable to connect to the socket server by opening the vueJS app on differnet PC (also connected to the same wifi as the PC serving the apps) so the iPad is not the issue here.
Could there be something with my local network that would be blocking the connection?
I have tried setting up the socket connection with plain socket.io client, vue-socketIO, and vue-socketIO-extended but each library had the same issue. Here is my code using vue-socketIO-extended:
main.js
import VueSocketIOExt from 'vue-socket.io-extended';
import { io } from 'socket.io-client';
const socket = io('http://localhost:3000');
Vue.use(VueSocketIOExt, socket);
App.js
sockets: {
connect() {
// Fired when the socket connects.
console.log('connect')
},
disconnect() {
console.log('disconnect')
}
}
server.js
const app = require('express')();
const http = require('http').createServer(app);
const io = require('socket.io')(http, {
cors: {
origins: ['http://localhost:8080']
}
});
app.get('/', (req, res) => {
res.send('<h1>Hey Socket.io</h1>');
});
io.on('connection', (socket) => {
console.log('a user connected');
socket.on('disconnect', () => {
console.log('user disconnected');
});
socket.on('my message', (msg) => {
io.emit('my broadcast', `server: ${msg}`);
});
});
http.listen(3000, () => {
console.log('listening on *:3000');
});
That's because the browser tries to connect to the WS server at http://localhost:3000, localhost resolves to IP 127.0.0.1 which is the loopback address of your device, on your iPad localhost is the iPad and there is nothing running on 127.0.0.1:3000 on the iPad.
You need to use the IP of the device that runs your server, Ex:
const socket = io('http://192.168.0.2:3000');

io.sockets.emit() won't work in production

I am trying to setup a socket in production like so:
client :
import openSocket from 'socket.io-client';
function handleSomething() {
let socketServer = 'https://staging.app.xxx.eu:9999';
const socket = openSocket(socketServer);
socket.on('calendlyHook', () => {
console.log("*** HERE");
...
socket.emit('closeSocket');
socket.close();
socket.removeAllListeners();
});
}
server :
const app = require('express')();
const http = require('http').createServer(app);
const io = require('socket.io')(http);
function openSocket() {
io.close();
io.set('origins', '*:*');
io.on('connection', (client) => {
console.log('Socket connected');
client.on('closeSocket', () => {
io.close();
io.removeAllListeners();
console.log('Socket closed');
});
});
const port = 9999;
io.listen(port);
console.log('*** listening on port ', port);
}
Then server-side, another function tries the following:
io.emit('calendlyHook');
or
io.sockets.emit('calendlyHook');
I have several issues in production (none of which happen on localhost):
console.log('*** listening on port ', port) is working fine
console.log('Socket connected') is not happening
io.emit('calendlyHook') or io.sockets.emit('calendlyHook') are not doing anything
I do not have any web server proxy set up on that url.
What is wrong here? Thanks!

How to send message to node js socket.io server from django server?

I have a node.js socket.io server as well as django server. Socket server has some clients connected with it. Now I want to send some messages from django server to the socket.io server so that it can broadcast these messages to its connected client.
Currently I am using pubsub by creating a redis server. But it's not working and no connection request is created with nodejs server:
Please suggest me a good way.
Thanks in advance.
Code in django:
import redis
client = redis.StrictRedis(host='localhost', port=6379, db=5)
client.publish('message', json.dumps({'query': {'token': jwt.encode({'user': 'admin'}, settings.SOCKET_SECRET_TOKEN, algorithm='HS256').decode('utf-8')}}))
Code from nodejs server:
const server = require('http').createServer();
const io = require('socket.io')(server);
const hostname = '127.0.0.1';
const SECRET_KEY = '*******************************';
const port = 3000;
const jwt = require('jsonwebtoken');
server.listen(3000, hostname, () => {
console.log(`Server running at http://${hostname}:${port}/`);
});
io.use(function(socket, next){
if (socket.handshake.query && socket.handshake.query.token){
jwt.verify(socket.handshake.query.token, SECRET_KEY, function(err, decoded) {
if(err) return next(new Error('Authentication error'));
socket.decoded = decoded;
next();
});
} else {
next(new Error('Authentication error'));
}
})
.on('connection', function(socket) {
console.log("Co nnection established");
socket.on('message', function(message) {
io.emit('message', message);
});
});

Socket.io (emit, on) not working - Node JS

I am working on a node JS application, where I am trying to use socket.io following this tutorial. Until this tutorial everything is fine, even the client is connected to the server through the socket, as it display a message on connection. But I don't know why my code isn't working on emit, and on event, and event handler.
Below is my Code on server side :
const express = require("express");
const app = express();
const scrap = require("./algorithm");
const mysql = require("mysql");
const ms_connect = mysql.createConnection({
host:'localhost',
user:'root',
password:'',
database:'scrapper_db'
});
const server = app.listen(8000, function(){ console.log('Listening on 8000'); });
const io = require("socket.io").listen(server);
app.use(express.static(__dirname + "/"));
io.on("connection",function(socket){
console.log("Sockets Connection Made ! " + socket.id);
socket.emit("testing",{data:"I am tested"});
io.on("disconnect",function(){
console.log("Client Disconnected !");
})
})
//mySQL Conection
ms_connect.connect(function(err){
if(err) console.log(err);
ms_connect.query("Select * FROM test",function(err,rows,fields){
if(err) console.log("Error Executing Query");
})
})
app.get("/scrap",function(req,res){
res.sendFile(__dirname+"/index.html");
})
Client side code :
var socket = io.connect('http://localhost:8000/scrap');
console.log(socket.connected); //returns false :(
socket.on("testing", function(d) {
console.log(d);
});
In the client side, the socket.connected object returns false, but on server side it says connected. I don't know how , and
I am using third link from this socket.io cdnjs server.
You are doing io.connect('http://localhost:8000/scrap') but the scrap is not mentioned anywhere on the server side. It should be io.connect('http://localhost:8000/'). Pointing to your HTML file is not needed because the socket.io server and your webserver are unrelated.
Also as pointed out by #TommyBs you should use
socket.on('connect', () => { console.log(socket.connected); });
to check if you are connected because connecting is asynchronous so it will not have connected yet by the time you do console.log(socket.connected);
The whole client code would be
var socket = io.connect('http://localhost:8000');
socket.on('connect', () => { console.log(socket.connected); });
socket.on("testing", function(d) {
console.log(d);
});
Change http://localhost:8000/scrap to http://localhost:8000/ in the client code. You're connecting to the wrong route.

Using Socket.io in React Native and Hapi Server

I'm trying to setup a simple socket io system for my React Native App (using Expo) to send messages back and forth from my Node Hapi server. Right now I have a print out on the Server to print when a connection is established however it is never printed. My Node server is hosted on a Amazon AMI instance using port 3030. Here are some code snippets. Any idea why the connection is not being made?
Server Socket IO Code:
const io = require('socket.io')(server.listener);
io.on('connection', (socket) => {
console.log('Socket connection established.');
socket.emit('connection', true);
});
Client Socket IO Code:
const io = require('socket.io-client');
componentDidMount() {
this.socket = io('http://{my_aws_instance_public_ip}:3030', {
transports: ['websocket']
});
this.socket.on('connect_error', (err) => {
console.log(err)
});
}

Resources