57

I am using Socket.io with Express. In my project I have a login page and a home page. When I do successful login, I navigate to localhost:3000/home where I get this error:

GET http://localhost:3000/socket.io/?EIO=3&transport=polling&t=1418187395022-0 404 (Not Found)

I did not do any modification in my app.js (project created by express ).

index.js:

var express = require('express');
var router = express.Router();
var http = require('http');
var fs = require('fs');
var io = require('socket.io')(http);
/* GET home page. */
router.get('/', function(req, res) {
  res.render('index', { title: 'Express' });
});

router.get('/home', function(req, res) {
  res.render('home', { title: 'Express' });
});

io.on('connection', function(socket){
    console.log("User Connected");
  socket.on('chat message', function(msg){
    io.emit('chat message', msg);
    console.log("Message");
  });
   socket.on('disconnect', function(msg){
    console.log("User DisConnected");
  });

});

router.post('/authenticate', function(req, res) {
    fs.readFile("./public/Verification/Users.json", "utf8", function (err, data) {
        if (err) 
            console.log(err);
        else{
            var result = JSON.parse(data);
            for(var i=0;i<result.Users.length;i++){
                if(req.body.username == result.Users[i].username && req.body.password ==     result.Users[i].password){
                    console.log("Success!!!!!!!!!!!!!!");
                    res.location("home");
                    res.redirect("home");
                }
            }
        }
        });
});

module.exports = router;

In my layout.jade I defined Socket.io like this:

script(src='https://cdn.socket.io/socket.io-1.2.0.js')
leonheess
  • 16,068
  • 14
  • 77
  • 112
Zee
  • 8,420
  • 5
  • 36
  • 58
  • Where is your express server configured to listen on port 3000? I don't see that part anywhere? And, it would need to be before you hook up io server side. – jfriend00 Dec 10 '14 at 06:16
  • By default it is listening to 3000. I did not configure anything. – Zee Dec 10 '14 at 06:26
  • There is no default on port 3000 that I'm aware of. If localhost:3000/home generates an error, then you don't have your web server working properly on port 3000. Which version of Express are you running? – jfriend00 Dec 10 '14 at 06:36

6 Answers6

84

If you're running Express 4, it appears to me like you're missing the lines of code:

var app = express();
var server = app.listen(3000);

That will start your web server and set it to port 3000. See the bone simple Express 4 app here: http://expressjs.com/4x/api.html

And, then to start up socket.io, you would add:

var io = require('socket.io').listen(server);

And, there is no need for this line:

var http = require('http');
jfriend00
  • 683,504
  • 96
  • 985
  • 979
38

Since I was battling with this issue for the past 5 hours. And this is the first result in google.

Of course its 2015 and some of the code has changed.

I think currently the best start of the index.js code is:

var express = require('express'),
    http = require('http');
var app = express();
var server = http.createServer(app);
var io = require('socket.io').listen(server);

server.listen(3000);

The order is highly important.

My problem was, that everything was installed properly and node was listening. However the example.com/socket.io/socket.io.js and example.com/socket.io/?eio=... was 404 not found. However, when I tried example.com:3000/socket.io/socket.io.js everything worked. So now was the question, how to change the getJSON query to have the port part.

So the solution was to edit the main.js, that is being added to the index.html, where your chat is. There is:

var socket = io();

to be replaced with

var socket = io.connect('http://example.com:3080');

This corrects the getJSON queries URL and adds the correct port and no more 404. I hope it helps someone in the future.

Kalle H. Väravas
  • 3,579
  • 4
  • 30
  • 47
  • 3
    The selected solution did not work but this one did :) Thank you :) – Titouan Launay Jul 13 '15 at 19:41
  • I will also add a note here of a problem, that everyone starting with these sockets. That those nodes do not stay alive. When you close your console, they will die out. For that you have to install an addon, that will keep the nodes alive. I sadly do not remember anymore, but I think it was elephant.io. Nevertheless you need something extra to keep the node alive. – Kalle H. Väravas Aug 25 '15 at 09:13
  • I tried to see the nginx conf, and added following line there: – undefined Aug 18 '17 at 06:22
  • var socket = io.connect('http://example.com:3080'); // this port number took few hours as I simply copy/pasted it :) Its 3080, instead of 3000. – 1JD Jun 15 '20 at 23:32
8

Please change your config to this

var express = require('express');

// App setup
var app = express();
var socket = require('socket.io')

var server = app.listen(4000, function(){
    console.log('listening for requests on port 4000,');
});

let io = socket(server)
io.on('connection', function(socket){
  console.log(`${socket.id} is connected`);
});
Josef Korbel
  • 1,168
  • 1
  • 9
  • 32
IAMSTR
  • 618
  • 8
  • 12
3

This is how i solve it on server side (2018):

const app = express();
const socketIO = require('socket.io');

const server = express()
  .use(app)
  .listen(PORT, () => console.log(`Listening Socket on ${ PORT }`));

const io = socketIO(server);

On client side

<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.0.1/socket.io.js"></script>

It looks easy but I spent hours before I found the solution since the solutions above didn't work for me.

MatMis
  • 309
  • 3
  • 16
  • 3
    what's the point of doing `app = express();` and then `server = express().use(app)` ? Is it on purpose or it's just a mistake? – Dawid Zbiński Apr 02 '19 at 12:17
3

For anyone doing this with nginx proxying to node.js, the problem might be the nginx conf instead of the node.js code.

You can test with a GET request (use curl, Postman, or browser) to http://localhost/socket.io/ (with the trailing slash) and one to http://localhost:3000/socket.io/

If http://localhost/socket.io/ gives 404 not found or "Cannot GET /", but http://localhost:3000/socket.io/ returns a response like:

{"code":0,"message":"Transport unknown"}

Then the backend node.js and socket.io are working, but nginx is not passing the request correctly.

Check it should look something like:

location /socket.io/ {
                proxy_set_header Upgrade $http_upgrade;
                proxy_set_header Connection "upgrade";
                proxy_http_version 1.1;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                proxy_set_header Host $host;
                proxy_pass http://127.0.0.1:3000;
}

In particular, note there is no trailing slash at the end of proxy_pass http://127.0.0.1:3000, since we want to pass the original request URI as is (i.e. including /socket.io).

From the nginx proxy_pass docs:

If the proxy_pass directive is specified with a URI, then when a request is passed to the server, the part of a normalized request URI matching the location is replaced by a URI specified in the directive:

location /name/ {
    proxy_pass http://127.0.0.1/remote/; } 

If proxy_pass is specified without a URI, the request URI is passed to the server in the same form as sent by a client when the original request is processed, or the full normalized request URI is passed when processing the changed URI:

location /some/path/ {
    proxy_pass http://127.0.0.1; }

The header requirements are covered at https://www.nginx.com/blog/nginx-nodejs-websockets-socketio/ (essentially websocket requires the Upgrade header which requires HTTP/1.1)

Burrito
  • 1,475
  • 19
  • 27
  • i have my nodejs socket deployed on AWS, with http the same code works fine but with https (with loadbalancer introduced though there is one active instance in LB) the socket connection keeps droping. I troubleshoot your steps and I am able to receive this ````{"code":0,"message":"Transport unknown"}````. What could be wrong with nginx? – Mr. Jay Nov 16 '21 at 20:43
  • I see this error : ````````2021/11/13 16:58:58 [error] 21285#21285: *5 connect() failed (111: Connection refused) while connecting to upstream, client: 172.31.27.33, server: , request: "GET /socket.io/?EIO=4&transport=polling HTTP/1.1", upstream: "http://127.0.0.1:8080/socket.io/?EIO=4&transport=polling", host: "domain.com" 2021/11/13 17:24:49 [error] 22100#22100: *2 connect() failed (111: Connection refused) while connecting to upstream, client: 172.31.27.33, server: , request: "POST /socket.io/?EIO=4&transport=polling&sid=xLc-Bz_iYKAXXXXXX- HTTP/1.1"```` – Mr. Jay Nov 16 '21 at 20:44
1

just call the listen of the server and with the callback I passed the server instance to module.

part of the bin/www file from express app

var server = http.createServer(app);
server.listen(port, function () {
  console.log('app listening on *:' + port);
  require('../socket')(server);
  console.log('socket server will be on *:' + port);
});

server.on('error', onError);
server.on('listening', onListening);

and this is how my socket module socket.js

var io = {};

module.exports = (server, serveradmin) => {
  io = require('socket.io')(server);
  io.on('connection', function (socket) {
    console.log(socket + ' a user connected');
  });
}

all of the socket listeners and emits managing from here.

Subhash
  • 545
  • 7
  • 11