1

If I have a node express server running on port 5003

import express from 'express'
import { createServer } from 'http'
import { Server } from 'socket.io'

const app = express()
const prod = process.env.NODE_ENV === 'production'
const port = process.env.PORT || prod ? 5003 : 4000
const httpServer = createServer(app)

const io = new Server(httpServer, {
  cors: {
    origin: '*',
    methods: ['GET', 'POST']
  }
})

const connections = []

io.on('connection', (socket) => {
  connections.push(socket)
  console.log(`Socket id ${socket.id} connected`)

  socket.on('disconnect', () => {
    connections.splice(connections.indexOf(socket), 1)
  })
})

httpServer.listen(port, () => console.log(`App listening on port ${port}.`))

And a client connecting the socket.io to the server

const socket = io(`http://localhost:5003`)

What would the nginx server block configuration be?

The url where this app is at is like this:

https://my.domain.com/myapp

And my server blocks are:

geo $authentication {
  default "Authentication required";
  `Some ip number` "off";
}

server {
  listen         80 default_server;
  listen    [::]:80 default_server;
  server_name my.domain.com;
  return 404; # managed by Certbot
}

server {
  listen 443 ssl http2;
  listen [::]:443 ssl http2;
  ssl_certificate /etc/letsencrypt/live/my.domain.com/fullchain.pem; # managed by Certbot
  ssl_certificate_key /etc/letsencrypt/live/my.domain.com/privkey.pem; # managed by Certbot

  include /etc/letsencrypt/options-ssl-nginx.conf;
  ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;

  server_name my.domain.com;
  client_max_body_size 200M;
  
  root /var/www/;
  index index.php index.html index.htm;

  location / {
    add_header Access-Control-Allow-Origin *;
    auth_basic $authentication;
    auth_basic_user_file /var/www/.htpasswd;
    try_files $uri $uri/ =404;
  }

  # Here is for example the app where I am running socket.io from
  location /myapp {
    auth_basic $authentication;
    auth_basic_user_file /var/www/.htpasswd;
    try_files $uri $uri/ =404;
  }

  # If this app has some sort of api route for express I do a proxy pass
  location /api/upload/ {
    proxy_pass http://localhost:5003/api/upload;
  }
Álvaro
  • 117
  • 1
  • 2
  • 8

1 Answers1

3

Here is an example NGINX configuration block for webscokets. Notice how the connection is upgraded if a valid websocket connection is made to the end point http://127.0.0.1:8080/wsapp

More at NGINX as a WebSocket Proxy

location /wsapp {
    proxy_pass http://127.0.0.1:8080;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "Upgrade";
    proxy_set_header Host $host;
    proxy_hide_header 'Access-Control-Allow-Origin';
}
suchislife
  • 356
  • 4
  • 11
  • This example is for a subfolder commonly referred to as an endpoint. That way NGINX doesn't `try_files` a path that is meant only for websockets to connect. No html or PHP is ever rendered at this end point. It accepts webscoket connections or nothing at all. – suchislife Feb 19 '21 at 18:49
  • When I do this I get a CORS message, I am making the connection for socket io to `http://127.0.0.1:8080/wsapp` and added the location endpoint – Álvaro Feb 19 '21 at 18:53
  • I've updated the answer to use NGINX's `proxy_hide_header` directive. It could be that the server behind your `proxy_pass` is setting the Access-Control-Allow-Origin header. – suchislife Feb 19 '21 at 19:07
  • So are you saying that the socket.io should connect like this `const socket = io('http://127.0.0.1:5003/wsapp')` obviously I also changed the nginx proxy to 5003? I still get CORS thou – Álvaro Feb 19 '21 at 19:09
  • More like `const socket = io('wss://127.0.0.1:5003/wsapp')` WSS for SSL and WS for NON-SSL. I see your URL is not HTTPS but your nginx.conf example is. – suchislife Feb 19 '21 at 19:11
  • Even with that I still get CORS `Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at https://127.0.0.1:5003/socket.io/?EIO=4&transport=polling&t=NUxjfrP` – Álvaro Feb 19 '21 at 19:14
  • The following example disables the HTTP long-polling transport: `const socket = io('wss://127.0.0.1:5003/wsapp', { transports: ["websocket"] });` – suchislife Feb 19 '21 at 19:17
  • Now I get `Firefox can’t establish a connection to the server at wss://127.0.0.1:5003/socket.io/?EIO=4&transport=websocket.` – Álvaro Feb 19 '21 at 19:19
  • This socket.io page should help you with the client side. [https://socket.io/docs/v3/client-initialization/index.html](https://socket.io/docs/v3/client-initialization/index.html) – suchislife Feb 19 '21 at 19:21
  • It turned out to be a problem with having the PM2 process manager on cluster mode, the moment I changed it to normal mode it started to work – Álvaro Feb 19 '21 at 21:05
  • Excellent. If the answer at least addresses the NGINX webscoket part, feel free to accept. – suchislife Feb 19 '21 at 22:04