Connecting to a WebSocket server that is hosted along with express app

Hello. So I am currently working on a server for my userscript for an online game, but I am having some issues with the websocket server I use for the chat part.
I started this project over a year ago, at that time I was barely considered a starter. I relied on AI assistants and codes copied from elsewhere. Well, the front end went fine but my back end skill really sucks and AI couldn’t help much when it comes to specific problems like this.
Three days ago I decided to start working on the chat function and eventually chose WebSockets to achieve it. Everything went fine locally, when I connect to it with ws://localhost:3000. So I deployed it to render after the final bugfixes, but I just couldn’t connect to the WebSockets server through wss://something.onrender.url:8080. Everything else went fine, the post and gets.

userscript.html?name…481-e9c05f590d90:51 WebSocket connection to 'wss://sshc-server-r1.onrender.com/' failed: 

The console does not help a lot.
Nothing shows up on server console.
I have looked into many solutions on the render community or stackoverflow, but none of them seemed to work for me.
remove the port number
Yes, I have tried wss://sshc-server-r1.onrender.com.
hosting both servers on one port
Not sure if this works but I think it wont go well with my project… or me because of the lack of skill. Many of the codes are about the POST and GET and I have some kind of variables that constantly updates, and is used by both of the servers.
Important lines of the codes:
Client

const socket = new WebSocket('wss://something.onrender.com');

socket.onopen = async () => {
    console.log('WebSocket connection established');
    await new Promise(resolve => setTimeout(resolve, 1000));
    window.appendMessage('System','Connected', 'system');
};

socket.onmessage = (event) => {
    console.log(event.data)
    const received=JSON.parse(event.data)
    if (received[0]==='plain') {
        window.appendMessage('N/A',received[1],'plain');
    } else if (received[0] === 'chat') {
        window.appendMessage(received[1],received[2],received[3]);
    }
};

socket.onerror = async (event) => {
    console.error('WebSocket error:', event);
    await new Promise(resolve => setTimeout(resolve, 1000));
    window.appendMessage('System',`WebSocket error: ${event}`, 'system');
};

socket.onclose = () => {
    window.appendMessage('System','Disconnected', 'system');
    console.log('WebSocket connection closed');
};

Server:

const express=require('express');
const cors = require('cors');
const app=express();
const WebSocket = require('ws');
const wss = new WebSocket.Server({ port: 8080 });
const msgTimeout = {};
const port=3000;
const status = []; // example of shared variable. 
// the GET request from client every 10 seconds adds the player username and the request timestamp to this array
// every 30 seconds the server checks if the last request time is 30 seconds ago, if true they will be defined as 'offline'.
// but im quite confused, if I am to separate them into two files, what should I do with the variable in GET request and the setInterval?
const limiters = {};
function rateLimit(req, res, next) {
  // some kind of rate limit codes
}
app.use(rateLimit);
app.use(cors());
wss.on('connection', (ws) => {
	console.log('WebSocket connection established');
	ws.on('message', (message) => {
	  // handles the client message
	});
	ws.on('error', (error) => {
	  console.error('WebSocket error:', error);
	});
	ws.on('close', () => {
	  console.log('WebSocket connection closed');
	});
});

app.use((req, res, next) => {
	res.setHeader('Access-Control-Allow-Origin', '*')  
	next() 
})
// some more get and post, but I only left this one below as an example
app.get('/api/status/:key',  rateLimit, (req, res) => {
	const xForwardedFor = req.headers['x-forwarded-for'];
    const ip = xForwardedFor ? xForwardedFor.split(',')[0].trim() : req.connection.remoteAddress;
	const key = req.params.key;
	const foundKey = userData[ip] ? userData[ip].key : null;
	if (key != foundKey) {
		res.status(401).json({ message:"Provided key does not match." });     
	} else {
		res.json(status);
	}
})
app.listen(port,()=>console.log('Server running on port '+port+'...'));

Please let me know if my expressions are wrong… I am still learning

Hi there,

Render only exposes a single port via our public proxy, you can’t have an Express server that listens on 3000 and WebSocket service, which listens on 8080. You need to do something like this example: https://www.npmjs.com/package/ws#external-https-server. Though use a http server or express instead of a https server.

Regards,

Keith
Render Support, UTC+10 :australia:

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.