Socket.io connection URL for production - node.js

When in development env, this works as expected,
Server Code... In development, I only specify the url in the client as const socket = io("http://localhost:3001"); Below is the server code.
const httpServer = createServer(app);
export const io = new Server(httpServer, {
cors: {
origin: "*",
},
path: "/socket.io/",
});
io.on("connection", (socket) => {
// make function calls
postOrderDeliveryStatus(socket);
// getOrders(socket);
// console.log("Socket Connected");
// close socket
socket.on("disconnect", () => {
socket.disconnect(true);
});
});
httpServer.listen(3001);
//mongoose
// console.log(process.env.CONNECTION_URL)
mongoose
.connect(process.env.CONNECTION_URL, {
useNewUrlParser: true,
useUnifiedTopology: true,
useCreateIndex: true,
})
.then(() =>
app.listen(PORT, () =>
winston.info(
`Server Running in ${process.env.NODE_ENV} mode on Port: ${PORT}`
)
)
)
.catch((error) => console.log(`${error} did not connect`));
mongoose.set("useFindAndModify", false);
Client...
const socket = io("http://localhost:3001");
const dispatchOrderHandler = () => {
const delivery_status = "DISPATCHED";
socket.emit("update-order", order._id, delivery_status);
// dispatch(getOrderDetailsToProcess(paramsOrderId)); //This dispatch alone can suffice
socket.on("updated-order", (updated_order) => {
dispatch(
getOrderDetailsToProcess(paramsOrderId, (order) => [
...order,
updated_order,
])
);
});
};
The error i get when sockets run is net::ERR_CONNECTION_REFUSED. I also tried
const socket = io(); without specifying the url since both the client and the server run on the same domain but that didn't either? What should the connection URL be in production since specifying the domain name hasn't worked? Am using heroku!

When using a hosting service, the service will provide the port to the client. You can access that port through process.env.PORT. To make the experience a bit more friendly to yourself as a developer, you can listen to the port using httpServer.listen(process.env.PORT || 3001);
As for the client, I believe you are right on using const socket = io();, although I haven't used socket.io in a while.

Use const socket = io("serverurl") to connect to a specific server.
I believe you can specify a port there as well.
So like for my website, I would do: const socket = io("us2.swordbattle.io:3000")

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');

socket.io showing polling-xhr.js:268 POST http://localhost:3000/socket.io/?EIO=3&transport=polling&t=ND_oTrA 404 (Not Found)

I am facing a socket.io connection issue. I know this question is already asked many times. And I tried solutions too from those questions but none of the solution work for me.
Here is my code:
const express = require('express');
var app = express();
var server = app.listen(8000, () => console.log('3000 is the port'));
var io = require('socket.io').listen(server);
const users = {};
io.on('connection', socket => {
console.log('connection ')
if (!users[socket.id]) {
users[socket.id] = socket.id;
}
socket.emit("yourID", socket.id);
io.sockets.emit("allUsers", users);
socket.on('disconnect', () => {
delete users[socket.id];
})
socket.on("callUser", (data) => {
io.to(data.userToCall).emit('hey', {signal: data.signalData, from: data.from});
})
socket.on("acceptCall", (data) => {
io.to(data.to).emit('callAccepted', data.signal);
})
});
Where am I making a mistake?
Your server is running on 8000 port but you logged that it is running on 3000. Hence try connecting it using localhost:8000 connection url.
You can also change server to run on port 3000 instead of 8000.
const PORT=3000;
const server = app.listen(PORT, () => console.log(`${PORT} is the port`));

Socket.io Node - React connection false

I'm not able to connect to socket on client for some reason. Logging socket all the time returns False. I tried official Socket.io app and it is working fine.. Can anyone help and let me know what I'm missing here?
Server
const app = require('express')()
const http = require('http').Server(app)
const io = require('socket.io')()
const router = require('./router')
const PORT = process.env.PORT || 8080
io.on('connection', (socket) => {
console.log('user connected');
socket.on('disconnect', () => {
console.log('user disconnected');
})
})
app.use(router)
app.listen(PORT, () => {console.log(`Server running on port ${PORT}`)})
Client
import queryString from 'query-string'
import io from 'socket.io-client'
let socket;
const Chat = () => {
const ENDPOINT = 'http://localhost:8080'
useEffect(() => {
socket = io(ENDPOINT)
console.log(socket);
})
return (
<div>
Chat
</div>
)
}
export default Chat
Solution
Server is listening on app instead http.listen(...)
You should pass http into socket.io:
const io = require('socket.io')(http);
Try using your ip address instead of the localhost

Socket.IO server.origins always returns '*' as the origin value (Nodejs)

I am trying to build a two way socket.io server/client connection. The server will remain behind one IP/domain and the client will behind a different IP. The point is to notify me when the server goes offline, in case of power outage or server failure. The issue I am having, is I am trying to secure the socket so not just anyone can connect to the socket. Socket.IO has a server.origins function that will return the origin of socket trying to connect. Their API documentation explains it like this.
io.origins((origin, callback) => {
if (origin !== 'https://foo.example.com') {
return callback('origin not allowed', false);
}
callback(null, true);
});
The issue I am having is whenever I connect to the socket.io server with socket.io-client the origin is always '*'.
Under potential drawbacks in there API is says:
"in some situations, when it is not possible to determine origin it may have value of *"
How do I get socket.io it see the IP where the socket connection request is coming from?
Once the connection is established I can use the socket information and see the IP where the socket lives, but the connection is already made. I am trying to stop rouge connections.
# Server
const express = require('express');
const app = express();
const chalk = require('chalk')
const server = require('http').createServer(app);
const io = require('socket.io')(server);
const cors = require('cors');
const port = 4424;
app.use(cors());
io.origins((origin, callback) => {
console.log(origin);
if (origin !== '*') {
return callback('origin not allowed', false);
}
callback(null, true);
});
io.on('connection', (socket) => {
console.log('Client connected...');
socket.on('join', (data) => {
console.log(data);
socket.emit('messages', 'Hello from server');
});
})
server.listen(port, () => console.log(chalk.blue(`Express started on port ${port}!`)));
Client:
# Client
const io = require('socket.io-client');
const socket = io('https://"MY DOMAIN THAT THE SERVER IS BEHIND"', { reconnect: true })
socket.on('connect', (data) => {
console.log("Connection successful");
socket.emit('join', 'Hello World from client');
});
socket.on('connect_error', (error) => {
console.log("Connection error");
});
socket.on('disconnect', (timeout) => {
console.log("Connection disconnected");
})
socket.on('messages', (data) => {
console.log(data);
});
I have the server behind a NGINX server using SSL, and connected to the server with the client on a different IP and it goes through and creates the connection, but the Origin is always "*".
Actually I found out you can use middleware with Socket.io with the io.use() function. I just wrote a simple middleware that checks the incoming socket ip with a list of approved ips.
io.use((socket, next) => {
const ip = socket.handshake.headers['x-forwarded-for']
if (firewall(ip))
{
return next();
}
})
And firewall is a function that checks if the ip is in the array of approved ips.

Node.js, how to keep server alive after a client exits?

I have a simple p2p app, but when I connect and exit as another peer or client the server stops completely. I've looked into connection.setKeepAlive, but it doesn't work they way I thought it would. I simply want the connection to any other peers to persist if another one exits.
const net = require('net')
const port = 3000
const host = 'localhost'
const server = net.createServer((connection) => {
console.log('peer connected')
})
server.listen(port, () => {
console.log('listening for peers')
})
const client = net.createConnection(port, host, () => {
console.log('connected to peer')
})
In your script the port on which the server listen is the same that you use for the client connection, so the application is calling itself.
Here is a script that connect to its peer and disconnect every 2 seconds:
const net = require('net')
const myPort = 3001
const peerPort = 3002
const host = 'localhost'
const server = net.createServer((connection) => {
console.log('peer connected')
})
server.listen(myPort, () => {
console.log('listening for peers')
})
let connectionTest = function() {
const client = net.createConnection(peerPort, host, () => {
console.log('connected to peer')
});
client.on('close', (err) => {
console.log("connection closed");
});
client.on('error', (err) => {
console.log("error");
});
//TODO do stuff
client.end();
setTimeout(connectionTest, 2000);
}
setTimeout(connectionTest, 3000);
For every instance you should change the ports (myPort & peerPort)

Resources