Keep getting and posting /socket.io/?EIO=3&transport=polling&t=

Viewed 402

My backend in ExpressJS and NodeJS used to work well. I just realized that logs exploded the disk (the backend is still functional), because when the backend is on, it keeps trying:

kpi.js GET /socket.io/?EIO=3&transport=polling&t=NBiaEK6
index.js GET /socket.io/?EIO=3&transport=polling&t=NBiaEK6
index.js router.get *
kpi.js POST /socket.io/?EIO=3&transport=polling&t=NBiaER6
index.js POST /socket.io/?EIO=3&transport=polling&t=NBiaER6
Error: Not Found
    at /opt/funfun/app.js:99:13
    at Layer.handle [as handle_request] (/opt/funfun/node_modules/express/lib/router/layer.js:95:5)
    at trim_prefix (/opt/funfun/node_modules/express/lib/router/index.js:317:13)
    at /opt/funfun/node_modules/express/lib/router/index.js:284:7
    at Function.process_params (/opt/funfun/node_modules/express/lib/router/index.js:335:12)
    at next (/opt/funfun/node_modules/express/lib/router/index.js:275:10)
    at /opt/funfun/node_modules/express/lib/router/index.js:635:15
    at next (/opt/funfun/node_modules/express/lib/router/index.js:260:14)
    at /opt/funfun/routes/index.js:18:2
    at Layer.handle [as handle_request] (/opt/funfun/node_modules/express/lib/router/layer.js:95:5)
    at trim_prefix (/opt/funfun/node_modules/express/lib/router/index.js:317:13)
    at /opt/funfun/node_modules/express/lib/router/index.js:284:7
    at Function.process_params (/opt/funfun/node_modules/express/lib/router/index.js:335:12)
    at next (/opt/funfun/node_modules/express/lib/router/index.js:275:10)
    at Function.handle (/opt/funfun/node_modules/express/lib/router/index.js:174:3)
    at router (/opt/funfun/node_modules/express/lib/router/index.js:47:12)
    at Layer.handle [as handle_request] (/opt/funfun/node_modules/express/lib/router/layer.js:95:5)
    at trim_prefix (/opt/funfun/node_modules/express/lib/router/index.js:317:13)
    at /opt/funfun/node_modules/express/lib/router/index.js:284:7
    at Function.process_params (/opt/funfun/node_modules/express/lib/router/index.js:335:12)
    at next (/opt/funfun/node_modules/express/lib/router/index.js:275:10)
    at /opt/funfun/node_modules/express/lib/router/index.js:635:15
kpi.js GET /socket.io/?EIO=3&transport=polling&t=NBiaF8A
index.js GET /socket.io/?EIO=3&transport=polling&t=NBiaF8A
index.js router.get *
kpi.js POST /socket.io/?EIO=3&transport=polling&t=NBiaFFz
index.js POST /socket.io/?EIO=3&transport=polling&t=NBiaFFz
Error: Not Found
    at /opt/funfun/app.js:99:13
    at Layer.handle [as handle_request] (/opt/funfun/node_modules/express/lib/router/layer.js:95:5)
    at trim_prefix (/opt/funfun/node_modules/express/lib/router/index.js:317:13)
    at /opt/funfun/node_modules/express/lib/router/index.js:284:7
    at Function.process_params (/opt/funfun/node_modules/express/lib/router/index.js:335:12)
    at next (/opt/funfun/node_modules/express/lib/router/index.js:275:10)
    at /opt/funfun/node_modules/express/lib/router/index.js:635:15
    at next (/opt/funfun/node_modules/express/lib/router/index.js:260:14)
    at /opt/funfun/routes/index.js:18:2
    at Layer.handle [as handle_request] (/opt/funfun/node_modules/express/lib/router/layer.js:95:5)
    at trim_prefix (/opt/funfun/node_modules/express/lib/router/index.js:317:13)
    at /opt/funfun/node_modules/express/lib/router/index.js:284:7
    at Function.process_params (/opt/funfun/node_modules/express/lib/router/index.js:335:12)
    at next (/opt/funfun/node_modules/express/lib/router/index.js:275:10)
    at Function.handle (/opt/funfun/node_modules/express/lib/router/index.js:174:3)
    at router (/opt/funfun/node_modules/express/lib/router/index.js:47:12)
    at Layer.handle [as handle_request] (/opt/funfun/node_modules/express/lib/router/layer.js:95:5)
    at trim_prefix (/opt/funfun/node_modules/express/lib/router/index.js:317:13)
    at /opt/funfun/node_modules/express/lib/router/index.js:284:7
    at Function.process_params (/opt/funfun/node_modules/express/lib/router/index.js:335:12)
    at next (/opt/funfun/node_modules/express/lib/router/index.js:275:10)
    at /opt/funfun/node_modules/express/lib/router/index.js:635:15

kpi.js GET ... and index.js GET ... are what I print. Here is the code of opt/funfun/app.js:

// catch 404 and forward to error handler
app.use(function (req, res, next) {
  var err = new Error('Not Found');  // line 99
  err.status = 404;
  next(err);
});

Does anyone know what may be the reason?

2 Answers

This may happen if you have a socket.io client trying to connect to your backend, but your backend does not have a socket.io server configured or is not properly configured to accept connection and you are logging any errors in the error handler.

Make sure the socket.io client and server are properly configured. Please see the socket.io docs on how to setup the client and the server.

By default the client keeps trying to reconnect infinitely when the connection fails, you can prevent it from polling the server infinitely by setting the reconnectionAttempts options.

For example, this will prevent the client from polling the server after 10 failed attempts

const socket = io(serverURL, { reconnectionAttempts: 10 });

Also to minimize the size of your logs, don't log the entire error object when you are in production, you could update the error handler to log only relevant details

// catch errors and forward to error handler
app.use(function (req, res, next) {
    ...
    next(err);
});

//In the error handler 
app.use(function (err, req, res, next)  {
    //log only relevant details
    logger.info(err.message)
})

Since you are passing an Error to the next parameter, it will detects as an error and Express will use its default handler if you don't have any Error handler.

If you pass anything to the next() function (except the string 'route'), Express regards the current request as being an error and will skip any remaining non-error handling routing and middleware functions.

If you pass an error to next() and you do not handle it in a custom error handler, it will be handled by the built-in error handler; the error will be written to the client with the stack trace. The stack trace is not included in the production environment.

From: https://expressjs.com/en/guide/error-handling.html

So it might be because:

  1. You don't have error handler middleware, and Express default error handler is logging all of the error stack traces
  2. You have error handler, but it's logging all the error stack trace.

First, make sure you are running in production environment so the error stack trace doesn't get sent to the client

Set the environment variable NODE_ENV to production, to run the app in production mode.

If you want to pass data (error) to next middleware without it getting detected as an error, store it in res.locals instead, read more here.

app.use(function (req, res, next) {
    const err = new Error("Not Found");
    err.status = 404;
    res.locals.exception = err;
    next();
});

// Custom Error handler
app.use(function (req, res) {
    let err = res.locals.exception;
    // Add Minimum logging here if you want
    if(err.message === "Not Found") {
        return res.status(404).send();
    } else {
        return res.status(500).send();
    }

    // or
    return res.status(err.status).send(err.message);
});

or write your own actual custom error handler middleware (make sure to put it after the 404 error handler)

app.use(function (req, res, next) {
    const err = new Error("Not Found");
    err.status = 404;
    next(err);
});

// Actual Error handler Middleware, notice the first parameter is the error
app.use(function (err, req, res) {
    // Add Minimum logging here if you want
    if(err.message === "Not Found") {
        return res.status(404).send();
    } else {
        return res.status(500).send();
    }

    // or
    return res.status(err.status).send(err.message);
});

// -- or if you are using typescript --

// declare the error handler first
const errorHandler: ErrorRequestHandler = (err, req, res, next) => {
    // Add Minimum logging here if you want
    if(err.message === "Not Found") {
        return res.status(404).send();
    } else {
        return res.status(500).send();
    }

    // or
    return res.status(err.status).send(err.message);

}; 

// then use it
app.use(errorHandler);

I've been using the first option (res.locals) because on Typescript it doesn't support error handler middleware somehow. I just figured it out, adding it to example, found the solution from this github issue

Related