How to resolve a Socket.io 404 (Not Found) error?

node.jsExpresssocket.io

node.js Problem Overview


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')

node.js Solutions


Solution 1 - node.js

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');

Solution 2 - node.js

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.

Solution 3 - node.js

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`);
});

Solution 4 - node.js

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.

Solution 5 - node.js

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)

Solution 6 - node.js

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.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionZeeView Question on Stackoverflow
Solution 1 - node.jsjfriend00View Answer on Stackoverflow
Solution 2 - node.jsKalle H. VäravasView Answer on Stackoverflow
Solution 3 - node.jsIAMSTRView Answer on Stackoverflow
Solution 4 - node.jsmelshor essomassorView Answer on Stackoverflow
Solution 5 - node.jsBurritoView Answer on Stackoverflow
Solution 6 - node.jsSubhashView Answer on Stackoverflow