PirateApp
PirateApp

Reputation: 6260

Where do I add this websocket code in the new nuxt.js setup since it does not have server?

The library requires an instance of server which you create by calling http.createServer(app) meaning an instance of the running express app. You would use this server instance now to listen to 3000 in the index.js file. Also create a sessionHandler which you obtain by calling session({}) with the express-session library

    const WebSocket = require('ws')
    function websocket({ server, sessionHandler, logger }) {
      // https://github.com/websockets/ws/blob/master/examples/express-session-parse/index.js, if you pass a server instance here 'upgrade' handler will crash
      const wss = new WebSocket.Server({ noServer: true })
      function noop() {}
      function heartbeat() {
        this.isAlive = true
      }
      wss.on('connection', (ws, request, client) => {
        ws.isAlive = true
        ws.on('pong', heartbeat)
        ws.on('message', (msg) => {
          logger.info(`Received message ${msg} from user ${client}`)
          ws.send(true)
        })
      })
      server.on('upgrade', (request, socket, head) => {
        sessionHandler(request, {}, () => {
          logger.info(`${JSON.stringify(request.session)} WEBSOCKET SESSION PARSED`)
          wss.handleUpgrade(request, socket, head, (ws) => {
            wss.emit('connection', ws, request)
          })
        })
      })
      // TODO use a setTimeout here  instead of a setInterval
      setInterval(function ping() {
        // wss.clients => Set
        wss.clients.forEach(function each(ws) {
          if (ws.isAlive === false) return ws.terminate()
          ws.isAlive = false
          ws.ping(noop)
        })
      }, 30000)
      return wss
    }
    module.exports = websocket

Upvotes: 5

Views: 10955

Answers (1)

User 28
User 28

Reputation: 5168

You can create a custom module and use nuxt hooks to get a server instance on listen event.

Create modules/ws.js:

const WebSocket = require('ws')
const wss = new WebSocket.Server({ noServer: true })

wss.on('connection', ws => {
  ws.on('message', message => {
    console.log('received: %s', message);
  })
  ws.send('Hello')
})

export default function () {
  this.nuxt.hook('listen', server => {
    server.on('upgrade', (request, socket, head) => {
      wss.handleUpgrade(request, socket, head, ws => {
        wss.emit('connection', ws);
      })
    })
  })
}

And register the module in nuxt.config.js:

export default {
  modules: [
    '~/modules/ws'
  ]
}

In your case you could create a module directory instead of a single file to store multiple related files.

Create modules/ws/index.js

const websocket = require('./websocket') // this is your file

export default function () {
  this.nuxt.hook('listen', server => {
    websocket({
      server,
      sessionHandler (request, _, cb) { // example
        cb()
      },
      logger: console // example
    })
  })
}

Then copy your file to modules/ws/websocket.js. You can use module.exports which is CommonJS format or change it into ES Module format, Nuxt(Webpack) can handle that.

In your code I notice that ws.send(true) cause an error TypeError [ERR_INVALID_ARG_TYPE]: The first argument must be of type string or an instance of Buffer, ArrayBuffer, or Array or an Array-like Object. Received type boolean (true) which basically mean you cannot send boolean.

Upvotes: 13

Related Questions