Vicfou
Vicfou

Reputation: 11

How to use Nginx unit with ws package in node js

I've set up an http server that can receive rest and websocket requests using the following code It works fine when I launch the server via node, but if I launch the server with ngnix unit the server launches but I can't receive data via my socket.

const assert = require('assert');
const Websocket = require('ws');
const express = require('express');
const app = express();
const port = 8080
assert.ok(process.env.WS_SERVER, 'You must define the WS_SERVER env variable');
console.log(`setting up record path at ${process.env.WS_SERVER }`);

//
async function handleUpload(socket) {

    socket._recvInitialMetadata = false;
    socket.on('message', function(data, isBinary) {
      console.log(data)
      if(socket._recvInitialMetadata) return
      socket._recvInitialMetadata = true
    });

    socket.on('error', function(err) {
      console.error({err}, 'stream upload: error');
    });
    socket.on('close', (data) => {
      console.info({data}, 'stream: close');
    });
    socket.on('end', function(err) {
      console.error({err}, 'stream upload: socket closed');
    });
}

// Config webServer
const wsServer = new Websocket.Server({ noServer: true });
wsServer.setMaxListeners(0);
wsServer.on('connection', handleUpload.bind(null));

// Config Express
app.use(express.urlencoded({ extended: true }));
app.use(express.json());
app.use('/', (req, res) => {
  res.send('Hello World!')
});
app.use((err, req, res, next) => {
  logger.error(err, 'burped error');
  res.status(err.status || 500).json({msg: err.message});
});

const server = app.listen(port, async () => {
  console.log(`app listening at http://localhost:${port}`);
});

server.on('upgrade', (request, socket, head) => {
  if(head === undefined) head = new Uint8Array() // Fix here cause ngnix-unit pass head value to undefined
  wsServer.handleUpgrade(request, socket, head, (socket) => {
    if (request.url !== process.env.WS_SERVER) return socket.destroy();
    wsServer.emit('connection', socket, request);
  });
});

var unitSocketServer = undefined
try {
  require.resolve('unit-http')
  unitSocketServer = require('unit-http/websocket').server({httpServer : server})
  console.log('unit-http websocket server is loaded')
} catch {

}

Here my ngnix-unit configuration (I'm using the 1.29 v)

{
    "listeners": {
        "*:8080": {
            "pass": "applications/app-test"
        }
    },
    "applications": {
        "app-test": {
            "type": "external",
            "working_directory": "/var/www/app",
            "executable": "/usr/bin/env",
            "user": "www-data",
            "group": "www-data",
            "arguments": [
                "node",
                "--loader",
                "unit-http/loader.mjs",
                "--require",
                "unit-http/loader",
                "app.js"
            ],
            "processes": {
                "max" : 12,
                "spare" : 3,
                "idle_timeout" : 30
            }
        }
    }
}

Upvotes: 1

Views: 145

Answers (0)

Related Questions