0

I have a server in node.js based on Express. The modules name is www:

    const http = require('http');
    var app = require('../app');
    server = http.createServer(app);
    server.listen(config.serverPort);
    module.exports = server;

In another module I want to define a socket.io connection. I am not able to pass the var server to the other module. What is my mistake? If I run the code in one script everything works fine. So it looks like there is a problem passing the var server to the other module.

    var www = require('./www');
    var io = require('socket.io')(www.server, {
        cors: {
            origin: '*',
            methods: ["GET", "POST"]
        }
   });

io.on('connection', function(socket){
    console.log('a user connected: ' + socket.id);
    
    });

My failure looks like:

::ffff:192.168.178.11 - - [27/Feb/2021:17:24:53 +0000] "GET /socket.io/?EIO=4&transport=polling&t=NVaXOrG&b64=1 HTTP/1.1" - -

::ffff:192.168.178.11 - - [27/Feb/2021:17:24:58 +0000] "GET /socket.io/?EIO=4&transport=polling&t=NVaXQ3X&b64=1 HTTP/1.1" - -

::ffff:192.168.178.11 - - [27/Feb/2021:17:25:03 +0000] "GET /socket.io/?EIO=4&transport=polling&t=NVaXRHo&b64=1 HTTP/1.1" - -

::ffff:192.168.178.11 - - [27/Feb/2021:17:25:08 +0000] "GET /socket.io/?EIO=4&transport=polling&t=NVaXSW3&b64=1 HTTP/1.1" - -

Happy for some help! Thanks.

Harald
  • 243
  • 2
  • 12
  • You can do `app.set()`, then include express and call app.get(), or you could simply pass app to your module, i.e dependency injection – Lawrence Cherone Feb 27 '21 at 17:57

2 Answers2

1

First off, you have a circular require() loop where app and www are each requiring the other. You can't do that. One of the require() calls will just return null and cause you errors. The usual solution for a problem like this is to move the common code into a third module and have each of the first two require() in the third module to get access to the common code and not require each other.

Then, second, you also need to fix your import to match the way you are exporting the server.

When you do this:

module.exports = server;

That means you should do this on the import side of things:

const server = require('./www');
const io = require('socket.io')(server, { ... });

You aren't exporting a .server property, you are make the whole module.exports object be the server object itself. So, when you require() that module, you get the server object directly, not an object with a .server property.


Also (unrelated to your specific problem you asked about), you should declare your server object locally like this so you aren't accidentally creating a global variable:

const server = http.createServer(app);

And, you should be using let or const and not var. There is no reason to use var any more in nodejs development.

jfriend00
  • 683,504
  • 96
  • 985
  • 979
  • Thanks to all. I tried your answer, but it doesn´t work. I still get the log output shown above. Is there another solution? – Harald Feb 27 '21 at 19:09
  • I honestly do not understand, why the export shown by jfriend00 doesn´t work. Now, I have a function in my socket module, which I export. In the www module I require the socket module and export the server variable via the function. And this does work... But still looking for an answer for the initial problem... Still a lot to learn :-) – Harald Feb 27 '21 at 19:57
  • @Harald - It appears you have a circular `require()` loop where `www` and `app` are each requiring the other. Can't do that. One of them will end up importing a `null` which will cause an error. Why, oh why the designers of nodejs did not make this a thrown exception with a meaningful error message, I have no idea. It would have saved nodejs developers zillions of hours. Instead, one of the modules just ends up `null`. The usual solution is to break any common things out into a third module and have each module require the commons things from the third module and not require each other. – jfriend00 Feb 27 '21 at 21:33
0

Since you're exporting server via module.exports, you get access to it directly when you require('./www'). With www.server, you're trying to access the server property of the exported server which is why it's not working.

const server = require('./www')
const io = require('socket.io')(server,
  cors: {
    origin: '*',
    methods: ['GET', 'POST']
  }
})

Do check this answer to understand the difference between module.exports vs exports.


Btw, I would recommend moving the server.listen entrypoint to index.js (or a file of your choice) which should import the server from www.js

// www.js

const http = require('http');
const app = require('../app')
module.exports = http.createServer(app)

// index.js

const server = require('./www')
server.listen(process.env.PORT || 3000)
Arun Kumar Mohan
  • 11,517
  • 3
  • 23
  • 44