1

I'm using a Ubuntu server on DigitalOcean to host an Nginx web server and a Node app that runs a WebSocket server. When attempting to connect to the IP of the server, I get the following message in the console:

WebSocket connection to 'ws://<server's public IP>' failed: Error during WebSocket handshake: Unexpected response code: 200

All I did to set up Nginx was to follow this guide, which simply tells you to install Nginx and adjust the UFW firewall. I didn't set up server blocks in Step 4, and I haven't touched any other config files.

After that, I put my index.html and client.js files in the /var/www/html directory to be served by Nginx.

index.html is a very simple HTML page that runs client.js. That JS file looks like this:

const ws = new WebSocket('ws://<public IP, same as above>:80');

ws.addEventListener('open', () => {
    const json = { message: 'hello from client!' };
    const jsonString = JSON.stringify(json);
    ws.send(jsonString);
});

ws.addEventListener('message', event => {
    const data = JSON.parse(event.data);
    console.log(data);
});

The server side Node app is websocket.js, and it looks like this:

const buffer = require('buffer');
const http = require('http').createServer();
const ws = require('ws');
const wsServer = new ws.Server({ server: http });

wsServer.on('connection', (socket) => {
    socket.on('message', (msg) => {
        console.log('received: ' + msg);
        socket.send(Buffer.from('hello from the server!'));
    });

    const json = { message: 'hello from server!' };
    const jsonString = JSON.stringify(json);
    socket.send(Buffer.from(jsonString));
});

http.listen(8080, () => console.log('listening on 8080'));

This file was placed at /root along with node_modules, package.json, and package-lock.json. Serving it alongside the client side code at /var/www/html didn't help. Of course, it was also running thanks to PM2, and I have also tried running without PM2 which made no difference.

Any help is appreciated, please let me know if there's any information I might have missed.

Makoren
  • 321
  • 1
  • 3
  • 12

1 Answers1

3

Turns out there are some extra steps you need to take in order to get Nginx and Node.js to play nicely.

I went to the /etc/nginx/sites-available/default and updated this block:

location / {
    try_files $uri $uri/ =404;
}

to this block:

location / {
    proxy_pass http://localhost:8080;  # change to your port if needed
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection 'upgrade';
    proxy_set_header Host $host;
    proxy_cache_bypass $http_upgrade;
    try_files $uri $uri/ =404;
}

And then updated my Node app to serve files through Express with app.use(express.static('/var/www/html'));.

Here are a couple of links that helped lead me to the right answer:

Node.js + Nginx - What now?

https://www.digitalocean.com/community/questions/how-to-run-node-js-server-with-nginx

And an extra link I found which tells you more about the Nginx directives used:

http://nginx.org/en/docs/http/ngx_http_proxy_module.html

Makoren
  • 321
  • 1
  • 3
  • 12