Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to set up a socket connection on a strapi server

I am trying to integrate socket.io with strapi. But unfortunately I have been unable to do so without any proper tutorial or documentation covering this aspect.

I followed along with the only resource I found online which is: https://medium.com/strapi/strapi-socket-io-a9c856e915a6 But I think the article is outdated. I can't seem to run the code mentioned in it without running into tonnes of errors.

Below is my attempt to implement it and I have been trying to connect it through a chrome websocket plugin smart websocket client But I am not getting any response when I try to run the server.

I'm totally in the dark. Any help will be appreciated

module.exports = ()=> {
  // import socket io
  var io = require('socket.io')(strapi.server)
  console.log(strapi.server) //undefined
  // listen for user connection
  io.on('connect', socket => {
  
      socket.send('Hello!');
      console.log("idit")

      // or with emit() and custom event names
      socket.emit('greetings', 'Hey!', { 'ms': 'jane' }, Buffer.from([4, 3, 3, 1]));

      // handle the event sent with socket.send()
      socket.on('message', (data) => {
        console.log(data);
      });

      // handle the event sent with socket.emit()
      socket.on('salutations', (elem1, elem2, elem3) => {
        console.log(elem1, elem2, elem3);
      });
    });
};
like image 898
Moiz Sohail Avatar asked Dec 01 '22 09:12

Moiz Sohail


2 Answers

So I found the solution. Yay. I'll put it here just in case anybody needs it.

boostrap.js

module.exports = async () => {
  process.nextTick(() =>{
    var io = require('socket.io')(strapi.server);
    io.on('connection', async function(socket) {

      console.log(`a user connected`)
      // send message on user connection
      socket.emit('hello', JSON.stringify({message: await strapi.services.profile.update({"posted_by"})}));


      // listen for user diconnect
      socket.on('disconnect', () =>{
        console.log('a user disconnected')
      });
    });
    strapi.io = io; // register socket io inside strapi main object to use it globally anywhere
  })

};

Found this at: https://github.com/strapi/strapi/issues/5869#issuecomment-619508153_

Apparently, socket.server is not available when the server starts. So you have to make use of process.nextTick that waits for the socket.server to initialize.

I'll also add a few questions that I faced when setting this up.

How do i connect from an external client like nuxt,vue or react?

You just have to connect through "http://localhost:1337" that is my usual address for strapi.

I am using nuxt as my client side and this is how set up my socketio on the client side

  1. I first installed nuxt-socket-io through npm
  2. Edited the nuxt.config file as per it's documention
modules:[
  ...
  'nuxt-socket-io',
  ...
],
io: {
    // module options
    sockets: [
      {
        name: 'main',
        url: 'http://localhost:1337',
      },
    ],
  },
  1. And then i finally added a listener in one of my pages.
created() {
    this.socket = this.$nuxtSocket({})
    this.socket.on('hello', (msg, cb) => {
      console.log('SOCKET HI')
      console.log(msg)
    })
},

And it works.

like image 189
Moiz Sohail Avatar answered Dec 05 '22 19:12

Moiz Sohail


A clean way to integrate third-party services into Strapi is to use hooks. They are loaded once during the server boot. In this case, we will create a local hook.

The following example has worked with [email protected].

  • Create a hook for socket.io at ./hooks/socket.io/index.js
module.exports = strapi => {
  return {
    async initialize() {
      const ioServer = require('socket.io')(strapi.server, {
        cors: {
          origin: process.env['FRONT_APP_URL'],
          methods: ['GET', 'POST'],
          /* ...other cors options */
        }
      })

      ioServer.on('connection', function(socket) {
        socket.emit('hello', `Welcome ${socket.id}`)
      })

      /* HANDLE CLIENT SOCKET LOGIC HERE */

      // store the server.io instance to global var to use elsewhere
      strapi.services.ioServer = ioServer
    },
  }
}
  • Enable the new hook in order for Strapi to load it - ./config/hook.js
module.exports = {
  settings: {
    'socket.io': {
      enabled: true,
    },
  },
};

That's done. You can access the websocket server inside ./config/functions/bootstrap.js or models' lifecycle hooks.

// ./api/employee/models/employee.js
module.exports = {
  lifecycles: {
    async afterUpdate(result, params, data) {
      strapi.services.ioServer.emit('update:employee', result)
    },
  },
};
like image 22
bonniss Avatar answered Dec 05 '22 19:12

bonniss