2

I've read some questions here on SO where some users are asking how to create a room using socket.io I've tried to apply the same concept and after reading the docs I've implemented on the heroku node websocket server I've deployed, the .joinmethod of the library but I'm unable to create a room. If i click on the button I've created on the UI, the console will log this error:

Access to XMLHttpRequest at 'https://mysocketserver.herokuapp.com/socket.io/?EIO=3&transport=polling&t=MqCuSYp' from origin 'https://localhost' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

Also I'm not able to verify if messages are sent. Where is the problem in my code?

server.js

const express = require('express');
const socketIO = require('socket.io');
const path = require('path');
const PORT = process.env.PORT || 3000;

const server = express()
  // .use(function(req, res){
  //   res.sendFile(__dirname + '/index.html');
  // })
  .listen(PORT, function(){
    console.log(`Our app is running on port ${ PORT }`);
  });

const io = socketIO(server);

var users = {};
var rooms = [];

io.on('connection', function(socket){
  console.log(socket);
  console.log('Client connected');
  socket.on('createroom', function(room){
    rooms.push(room);
    io.join(room);
  });
  socket.on('chat message', function(msg){
  //  console.log('message: ' + msg);
    io.to(rooms.room)
    .emit('chat message', msg);
    //io.emit('chat message', msg);
  });
  socket.on('disconnect', function(){
    console.log('Client disconnected');
  });
});

index.html

<!DOCTYPE html>
<html>
  <head>
    <title>Socket.IO chat</title>
    <script src="https://code.jquery.com/jquery-1.11.1.js"></script>
    <style>
      * { margin: 0; padding: 0; box-sizing: border-box; }
      body { font: 13px Helvetica, Arial; }
      form { background: #000; padding: 3px; position: fixed; bottom: 0; width: 100%; }
      form input { border: 0; padding: 10px; width: 90%; margin-right: .5%; }
      form button { width: 9%; background: rgb(130, 224, 255); border: none; padding: 10px; }
      #messages { list-style-type: none; margin: 0; padding: 0; }
      #messages li { padding: 5px 10px; }
      #messages li:nth-child(odd) { background: #eee; }
      #room { position: fixed; bottom: 94%;}
    </style>
  </head>
  <body>
    <form atcion="" name="room" id="room">
      <input type="text" id="r" type="text" autocomplete="off" /><button>Join</button>
    </form>
    <ul id="messages"></ul>
    <form action="" name="message">
      <input id="m" autocomplete="off" /><button>Send</button>
    </form>
    <!-- <script src="/socket.io/socket.io.js"></script> -->
    <script src="node_modules/socket.io-client/dist/socket.io.js"></script>
    <script>
      const socket = io('https://mysocketservice.herokuapp.com');
      $(function(){

        $('form[name="room"]').submit(function(e){
          e.preventDefault();
          socket.emit('createroom', $('#r').val());
          console.log(socket);
        });

        $('form[name="message"]').submit(function(e){
          e.preventDefault(); // prevents page reloading
          socket.emit('chat message', $('#m').val());
          $('#m').val('');
          return false;
        });
        socket.on('chat message', function(msg){
          console.log(msg);
          $('#messages').append($('<li>').text(msg));
        });
    });
    </script>
  </body>
</html>

What I want to do si simple, when an user insert a room name and then click on the join button, I want that the room is created and the user is added to that room. For this solution I'm thinking to implement a registration or login system, but I'm not sure on how to proceed because I'm new to node develop.

A better simple solution I'm also thinking to implement is to create a random string Math.random().toString(36) to append to the url, and then, when the user is on the page take that string and create an unique room where all the users on the same url can chat. Any help to find a working solution will be appreciated.

jihuuNI
  • 551
  • 2
  • 5
  • 17

1 Answers1

1

You need to enable cors in your server file.

  1. First of all, the cross-domain check is performed by the browser. When the JavaScript makes an XmlHttpRequest to a server other than its origin, if the browser supports CORS it will initialize a CORS process. Or else, the request will result in an error (unless the user has deliberately reduced browser security)

  2. When the server encounters the Origin HTTP header, the server will decide if it is in the list of allowed domains. If it is not in the list, the request will fail (i.e. the server will send an error response).

npm install cors

Then re-write your code like this below to enable cors

Server.js

const express = require('express');
const socketIO = require('socket.io');
const path = require('path');
const cors= require('cors');
const PORT = process.env.PORT || 3000;

const app = express()

app.use(cors());
  // .use(function(req, res){
  //   res.sendFile(__dirname + '/index.html');
  // })
 const server =  app.listen(PORT, function(){
    console.log(`Our app is running on port ${ PORT }`);
  });

const io = socketIO(server);

var users = {};
var rooms = [];

io.on('connection', function(socket){
  console.log(socket);
  console.log('Client connected');
  socket.on('createroom', function(room){
    // rooms.push(room);
    socket.join(room);
  });
  socket.on('chat message', function(msg){
    //  console.log('message: ' + msg);
  });
  socket.on('disconnect', function(){
    console.log('Client disconnected');
  });
});

I found this helpful on how to a create room.

Revised for Socket implementation.

Community
  • 1
  • 1
Akolade Adesanmi
  • 1,152
  • 11
  • 15
  • Thanks for the clarification, I will implement the CORS support in my server side code. For the rooms, will my implementation work or there is something to adjust also there? – jihuuNI Sep 07 '19 at 20:11
  • I've revised the solution. try it out – Akolade Adesanmi Sep 07 '19 at 20:19
  • I forgot to mention. install this for the client-side `npm install socket.io-client` – Akolade Adesanmi Sep 07 '19 at 20:27
  • It's already installed with the socket.io module, I'm loading the client library from that folder. – jihuuNI Sep 07 '19 at 20:31
  • I've tested the provided solution but it will not work. I'm also unable to create or join a room. – jihuuNI Sep 07 '19 at 20:36
  • First, can you see logs on your server console eg 'Client connected' – Akolade Adesanmi Sep 07 '19 at 20:41
  • no, if I implement CORS and join nothing will work! in particular join will result in an undefined function. – jihuuNI Sep 07 '19 at 22:31
  • have tested it with your source code it's working but I did some refactoring like where you have `io.join()`, `io` doesn't have that property(Join) I use a socket instance instead `socket.join(room)` and I've provided a link for more clarifications on socket for creating group. – Akolade Adesanmi Sep 08 '19 at 14:42
  • With the cors module it will not work. I've solved by using `res.setHeader("Access-Control-Allow-Origin", "*"); res.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept"); res.statusCode = 200;` to set the CORS headers. – jihuuNI Sep 08 '19 at 14:59
  • I was having this problem from the UI that is a page that i'm using for testing and it's located on localhost while the server is running on heroku. – jihuuNI Sep 08 '19 at 15:00