1

I have an existing project written in Express, where I've made a messaging system. Everything was working on POST/GET methods (to send and receive the messages). I wanted to make them appear in real time, so I installed socket.io both on the client and server side. In my server.js I added these lines:

const http = require("http");
const io = require("socket.io");
const server = http.createServer();
const socket = io.listen(server);

and changed my app.listen(...) into server.listen(...). Added also:

socket.on("connection", socket => {
    console.log("New client connected");
    socket.on('test', (test) => {
        console.log('test-test')
    });

    socket.emit('hello', {hello:'hello!'});

        socket.on("disconnect", () => console.log("Client disconnected"));
});

On the front part I put such code in the componentDidMount method:

const socket = socketIOClient();
socket.emit('test', {test:'test!'})
socket.on('hello', () => {
    console.log('aaa')
})

Now I got 2 problems. Although the console.log() works correctly, I get an error on the React app:

WebSocket connection to 'ws://localhost:3000/sockjs-node/039/lmrt05dl/websocket' failed: WebSocket is closed before the connection is established.

Is that normal?

Also, when I change app.listen(...) into server.listen(...) in the server.js file, my routing stops working. All the POST and GET methods don't work, because the server is responding endlessly. Is that possible to use the socket.io just on a specific method in a specific routing file?

I keep my routes that way: app.use('/api/user', user); where user is a router file.

UPDATE: full server.js require:

const express = require('express');
const mongoose = require('mongoose');
const dotenv = require('dotenv');
const bodyparser = require('body-parser');
const passport = require('passport');

const user = require('./routes/api/v1/User');
const company = require('./routes/api/v1/Company');

const http = require("http");
const io = require("socket.io");


const app = express();

dotenv.config();
app.use(passport.initialize());
require('./config/seed');

require('./config/passport')(passport);
const server = http.createServer();
const socket = io.listen(server);

1 Answers1

4

You're not initializing server properly. Try making the following change

// const server = http.createServer();
const server = http.createServer(app);

and make sure you listen on server and not io

server.listen(PORT_GOES_HERE)

[UPDATE] Working Example:

var app = require('express')();
var server = require('http').Server(app);
var io = require('socket.io')(server);

server.listen(80);
// WARNING: app.listen(80) will NOT work here!

// DO STUFF WITH EXPRESS SERVER
app.get('/', function (req, res) {
  res.sendFile(__dirname + '/index.html');
});

io.on('connection', function (socket) {
  socket.emit('news', { hello: 'world' });
  socket.on('my other event', function (data) {
    console.log(data);
  });
});

For more details check this: https://socket.io/docs/

Arti Singh
  • 401
  • 1
  • 3
  • 12
  • Thank you! It worked! Maybe you also know the answer to the second part of my question, if I could receive and emit websockets just inside specific routes? Like, let's say only inside `router.get('/message', passport.authenticate('jwt', {session: false}), (req, res) => {});`? – version_control Oct 14 '19 at 13:53
  • You're looking for namespaces. Read the docs here https://socket.io/docs/rooms-and-namespaces/ – Arti Singh Oct 14 '19 at 13:57
  • Feel free to prompt if that doesn't works for you or if it's not what you asked – Arti Singh Oct 14 '19 at 13:58
  • Thanks, but as I understand, I couldn't emit a socket.io from inside a route function? I'm asking because I would like to protect this connection with a JWT. – version_control Oct 14 '19 at 14:06
  • Resolved my problem combining this answer with that: https://stackoverflow.com/questions/36788831/authenticating-socket-io-connections – version_control Oct 16 '19 at 10:28