Socket.io port configuration with Heroku - node.js

I'm trying to get socket.io working on my heorku app, but I think I'm having some trouble defining the ports. On the backend I have my express app listening to the process.env port or 5000, and I have my socket.io port listening on 8000.
Node.js
const express = require("express");
const app = express();
const server = require('http').Server(app)
const io = require('socket.io')(server)
const socketPort = 8000;
io.listen(socketPort);
const port = process.env.PORT || 5000;
app.listen(port, () => console.log(`Server running on port ${port} !`));
And on my front end I have my socket to route requests to localhost:8000
Reactjs
const socket = io('http://localhost:8000')
//Open connection to backend
socket.on('connect', ()=>{
console.log("Connected");
})
It works just fine when I run it locally, but I can't get it working on Heroku - GET http://localhost:8000/socket.io/?EIO=3&transport=polling&t=MszLUDm net::ERR_CONNECTION_REFUSED
Is there a specific way I need to set up these ports? As far as I know I can only set up one process.env port. Should I be subbing something into the "localhost:8000" on the front end?
Thanks!

On the client side I ended up just declaring the socket like this:
const socket = io();
Leaving out the localhost:5000 part altogether.

Related

localhost:3000 not responding

I've just started learning node.js but when I try to launch the hello world code by writing on the terminal node server.js, localhost:3000 gives me the following error:
This page isn’t working;
localhost didn’t send any data.
ERR_EMPTY_RESPONSE
I've been searching for 2h now and I've found nothing. I've checked the port 3000 in cmd with netstat -a -n -o and it says that the port is listening (so I guess it is working). So what is preventing me from accesing to that port.
Here it my JS files:
server.js:
const http = require('http');
const app = require('./app');
const port = process.env.PORT || 3000;
const server = http.createServer();
server.listen(port);
app.js:
const { request } = require('express');
const express = require('express');
const app = express();
app.use((req, res, next) => {
res.status(200).json({
message: 'It works'
});
})
module.exports = app;
Add the required app to the createServer call:
const server = http.createServer(app);
In this way the http server can route your http requests to it.
Could process.env.PORT be set somewhere, causing your app to be hosted on that port instead?
An easy way to check would be to console.log the PORT variable in your script, and see if it has any value.
If it does have a value, trying going to localhost:PORT

Using sockets with express in production environment(heroku)

While working with localhost I used the following code to implement socket functionality-
Server Side
var express = require('express');
var app = express();
const io = require('socket.io')(5000);
Client Side
<script src="http://localhost:5000/socket.io/socket.io.js"></script>
<script>const socket = io.connect('http://localhost:5000');</script>
The above code worked fine for me locally. Earlier tried use the code given in the official documentation, but it did not work. I got a 404 error when trying to load socket.io.js file and it said 'io is not defined' on the client side. That code is given below-
Server Side
var app = require('express')();
var server = require('http').Server(app);
var io = require('socket.io')(server);
Client Side
<script src="/socket.io/socket.io.js"></script>
<script>var socket = io.connect('http://localhost');</script>
Now I need to deploy the app to Heroku and don't know how to do the socket functionality. I tried both the above ways but none worked in Heroku. I am getting '404 error' and 'io is not defined'. The server-side code is written in ./app.js and client-side code written in ./public/index.html.
How do I get this socket functionality to work in Heroku and also why is the official code not even working locally?
Trying to get the same thing working, don't have all the answers but on heroku you need to grab the port from the environment variable.
// Needed for Heroku serving
if (process.env.PORT > 0)
port = process.env.PORT;
else
port = 5000;
// create the express server (app) and the socket io server (io)
const app = express();
const server = app.listen(port, () => {
console.log("Listening on port: " + port);
});
const io = require('socket.io')(server);
Client Side
const socket = socketIOClient('APPNAME.herokuapp.com:80');
socket.emit("MsgType", "Payload")

Heroku socket.io server runs locally, but not anywhere else

Basically my socket.io server is only working for.. one computer only, I suppose. It works if I use Chrome, Chrome incognito, Edge. I tried using the app with my phone, while on the same Wifi, and that's where I encountered problems. It looked like socket.io just wouldn't work then. I feel like it's only working for one client (maybe ip, port issues?)
I use socket.io in pair with React js, and oh boy it was pain in the arse to make them work both locally and on Heroku.
Here's my server file /src/server/index.js
const express = require("express");
const http = require("http");
const socketIo = require("socket.io");
const axios = require("axios");
const port = process.env.PORT || 4001; // Only this port works for some reason
const index = require("./routes/index");
const app = express();
const path = require('path');
const server = http.createServer(app);
const io = socketIo(server); // < Interesting!
io = socketIo.listen(app);
io.configure(function () {
io.set("transports", ["xhr-polling"]);
io.set("polling duration", 10); // Recommended from online guys
});
app.use(express.static(path.join(__dirname, '../../index')));
app.get('/', (req, res, next) =>
res.sendFile(index))
io.on("connection", socket => {
console.log("New client connected");
})
server.listen(port, () => console.log(`Listening on port ${port}`));
I use config file to dynamically change the server and I import it every time I need to connect to my socket via socket.io-client
let server = 'ws://XXXXXXXXXXXXX.herokuapp.com/socket.io/?EIO=4&transport=websocket';
const env = process.env.NODE_ENV;
if (env === 'development') {
server = 'http://127.0.0.1:4001';
}
module.exports = server;
What could be the problem? Why is only working on my root computer? Could be a dyno problem or something else?
I'm a complete beginner with both heroku and socket.io, so any information would be helpful.
**EDIT:
I am not sure, but I feel like a server running in my VS Code made it work in my heroku app. I have turned it off and the server just keeps sending net::ERR_CONNECTION_REFUSED error.
Solution:
Using mars/heroku-cra-node buildpack is a must. It seperates react-ui and server code. Port config: const port = process.env.PORT || 4001,
Client listens for: let server = window.location.hostname
Also good to have a seperate config file for clientside that has the following:
const env = process.env.NODE_ENV;
if (env === 'development') {
server = 'http://localhost:4001';
}
module.exports = server;
Then you won't have to change ports and servers in development (VSCode) or production (Heroku).

Connect to a heroku server with socket.io

How would one go about connecting to a heroku node.js server? For example, I have a server named 'https://example.herokuapp.com/' that uses node.js. How would I connect to it from a normal javascript file running socket.io. The code might look something like this:
var socket = io();
socket.connect('https://example.herokuapp.com/', { autoConnect: true});
I have tried this and I get the output of
polling-xhr.js:261 GET http://file/socket.io/?EIO=3&transport=polling&t=LjFlRl1 net::ERR_NAME_NOT_RESOLVED
So would I need an IP for the heroku server? If so how do I get it and is it even possible with heroku. If you're wondering why I don't host the html file on heroku it's because I'm using it for a website and my web host doesn't support node.js hosting. So I decided to host the node.js server on heroku. Thanks for your help in advance.
Server code:
var express = require('express');
var app = express();
var server = require('http').createServer(app);
var io = require('socket.io')(server);
var port = process.env.PORT || 3000;
app.use(express.static(__dirname + '/public'));
server.listen(port, function () {
console.log('Server listening at port %d', port);
});
io.on('connection', function(socket){
console.log('connection' + socket.id)
socket.emit('ping', {
data: 'ping',
});
});

NodeJS and socket.io app on Heroku with 2 ports

My app has an express server listening on one port (process.env.PORT) and I also want a web socket using another port. I used to use Express 3 with this set-up:
var express = require('express'),
http = require('http'),
io = require('socket.io'),
app = express();
server = http.Server(app);
ioServer = io(server);
ioServer.on('connection', callback);
server.listen(process.env.PORT || 3000, function () {
console.log('App listening on ' + server.address().port);
});
The above code worked fine, as when creating ioServer, no specific port is required. However, after I switched to Express 4 and started using Heroku's WebSocket service, I had to specify a port like this:
var WebSocketServer = require('ws').Server,
port = 5000,
server = http.createServer(app);
server.listen(port);
var wss = new WebSocketServer({server: server});
wss.on('connection', callback);
app.listen(app.get('port'), function() {
console.log('Express server listening.'));
});
This new set-up never works because when I run the app on Heroku, I get an error complaining that the same port can't be used twice:
Error: listen EADDRINUSE :::40854
The set-up logic is essentially the same except for explicitly assigning a port in Express 4, so why did my code work with Express 3 but not Express 4? How should I fix this?
In your second code block, you can't call .listen() on both your server and on your app object. In this particular case (the way you've structured your code), you only want to call it on the server object, not on app.
This is the code from Heroku's dev page on this topic:
var WebSocketServer = require("ws").Server
var http = require("http")
var express = require("express")
var app = express()
var port = process.env.PORT || 5000
app.use(express.static(__dirname + "/"))
var server = http.createServer(app)
server.listen(port)
console.log("http server listening on %d", port)
var wss = new WebSocketServer({server: server})
console.log("websocket server created")
Also, your first code block is not running on two ports. As is usually the design for webSockets, a single port is used for both your web requests and your webSocket connections. The web server itself splits out the two types of connections based on the initial connection.

Resources