How to do it...

Build a Socket.IO client application that will connect to a Socket.IO server you will build next. Include a form where the user can type a username and a password to attempt to log in. The Socket.IO client will only be able to connect to the /home namespace after the user is logged-in:

  1. Create a new file named io-express-cli.html
  2. Add the following HTML content:
      <!DOCTYPE html> 
      <html lang="en"> 
      <head> 
          <meta charset="UTF-8"> 
          <title>Socket.IO Client</title> 
          <script src="http://localhost:1337/socket.io/socket.io.js">  
</script> <script
src="https://unpkg.com/@babel/standalone/babel.min.js">
</script> </head> <body> <h1 id="title"></h1> <form id="loginForm"> <input type="text" name="username" placeholder="username"/> <input type="password" name="password"
placeholder="password" /> <input type="submit" value="LogIn" /> <output name="logErrors"></output> </form> <script type="text/babel"> // Code here </script> </body> </html>
  1. Inside the script tag add the code in the next steps, starting from step 4
  2. Define constants that make a reference to the HTML elements that we will use:
      const title = document.getElementById('title') 
      const error = document.getElementsByName('logErrors')[0] 
      const loginForm = document.getElementById('loginForm') 
  1. Define a Socket.IO Manager:
      const manager = new io.Manager( 
          'http://localhost:1337', 
          { path: '/socket.io' }, 
      ) 
  1. Define two namespaces, one for /login and another one for /home:
      const namespace = { 
          home: manager.socket('/home'), 
          login: manager.socket('/login'), 
      } 
  1. Add an event listener for the welcome event that will be triggered by the server side once a connection is allowed to the /home namespace:
      namespace.home.on('welcome', (msg) => { 
          title.textContent = msg 
          error.textContent = '' 
      }) 
  1. Add an event listener for loginSuccess event that, when triggered, will ask the /home namespace to try and reconnect to the Socket.IO Server:
      namespace.login.on('loginSuccess', () => { 
          namespace.home.connect() 
      }) 
  1. Add an event listener for loginError event that will display an error when invalid credentials are provided:
      namespace.login.on('loginError', err => { 
          error.textContent = err.message 
      }) 
  1. Add an event listener for submit event that will get triggered when submitting the form. It will emit an enter event with data containing the provided username and password:
      loginForm.addEventListener('submit', event => { 
          const body = new FormData(loginForm) 
          namespace.login.emit('enter', { 
              username: body.get('username'), 
              password: body.get('password'), 
          }) 
          event.preventDefault() 
      }) 
  1. Save the file.

After this, build an ExpressJS application that will serve the Socket.IO client on the root path "/" and a Socket.IO server that will include the logic for logging the user:

  1. Create a new file named io-express-srv.js
  2. Initialize a new ExpressJS application and a Socket.IO server application. Also, include the express-session NPM module:
      const path = require('path') 
      const express = require('express') 
      const io = require('socket.io')() 
      const expressSession = require('express-session') 
      const app = express() 
  1. Define the path where new connections to Socket.IO server will be made:
      io.path('/socket.io') 
  1. Define an ExpressJS session middleware function with the given options:
      const session = expressSession({ 
          secret: 'MERN Cookbook Secret', 
          resave: true, 
          saveUninitialized: true, 
      }) 
  1. Define a Socket.IO namespace middleware that will use the previously created session middleware to generate a session object:
      const ioSession = (socket, next) => { 
          const req = socket.request 
          const res = socket.request.res 
          session(req, res, (err) => { 
              next(err) 
              req.session.save() 
          }) 
      } 
  1. Define two namespaces, one for /home and another for /login:
      const home = io.of('/home') 
      const login = io.of('/login') 
  1. Define an in-memory database or array of objects that will contain username and password properties. These define which users are allowed to login:
      const users = [ 
          { username: 'huangjx', password: 'cfgybhji' }, 
          { username: 'johnstm', password: 'mkonjiuh' }, 
          { username: 'jackson', password: 'qscwdvb' }, 
      ] 
  1. Include the session middleware in ExpressJS:
      app.use(session) 
  1. Add a route method for /home path that will serve our previously created HTML document containing the Socket.IO client:
      app.get('/home', (req, res) => { 
          res.sendFile(path.resolve( 
              __dirname, 
              'io-express-cli.html', 
          )) 
      }) 
  1. Use the session middleware in /home Socket.IO namespace. Then, check for every new socket if the user is logged in. If not, forbid the user to connect to this namespace:
      home.use(ioSession) 
      home.use((socket, next) => { 
          const { session } = socket.request 
          if (session.isLogged) { 
              next() 
          } 
      }) 
  1. Once a connection is made to the /home namespace, meaning that the user can log in, emits a welcome event with a welcome message that will be displayed to the user:
      home.on('connection', (socket) => { 
          const { username } = socket.request.session 
          socket.emit( 
              'welcome', 
              `Welcome ${username}!, you are logged in!`, 
          ) 
      }) 
  1. Use the Session Middleware in the /login Socket.IO namespace. Then, when the client emits an enter event with the provided username and password, it verifies the profile exists in the users array. If the user exists, set the isLogged property to true and the username property to the current user that has logged in:
      login.use(ioSession) 
      login.on('connection', (socket) => { 
          socket.on('enter', (data) => { 
              const { username, password } = data 
              const { session } = socket.request 
              const found = users.find((user) => ( 
                  user.username === username && 
                  user.password === password 
              )) 
              if (found) { 
                  session.isLogged = true 
                  session.username = username 
                  socket.emit('loginSuccess') 
              } else { 
                  socket.emit('loginError', { 
                      message: 'Invalid Credentials', 
                  }) 
              } 
          }) 
      }) 
  1. Listen on port 1337 for new connections and attach the Socket.IO server to it:
      io.attach(app.listen(1337, () => { 
          console.log( 
              'HTTP Server and Socket.IO running on port 1337' 
          ) 
      })) 
  1. Save the file
  2. Open a new Terminal and run:
      node io-express-srv.js  
  1. In your browser, visit:
      http://localhost:1337/home
  1. Login with valid credentials. For example:
      * Username: johntm
* Password: mkonjiuh
  1. If you logged in successfully, after refreshing the page, your Socket.IO client application will still be able to connect to /home and you will see a welcome message every time
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.16.46.131