Search code examples
javascriptnode.jsmongodberror-handlingbackend

How to prevent "*" route from running with the routes defined previously


I defined my app routes in that order

app.use(express.json());
app.use(express.static(`${__dirname}/public`));
app.use('/api/v1/tours', tourRouter);
app.use('/api/v1/users', userRouter);

app.all('*', (req, res, next) => {
  const error = new AppError(
    `This ${req.originalUrl} is not on the server`,
    404,
  );
  next(error);
});

app.use(globalErrorHandler);

The AppError is a class to customize the error object and the globalErrorHandler is function that send the error response according to the error object comes from next().

My problem is that the '*' routes runs with all the routes that I handled previous with the tourRouter. I don't know why this happens. It wasn't doing this, just happens once and still happening until the time I wrote this problem.

NOTE: Postman gives me the correct response from the routes I defined, but the terminal in VSC gives me the "cannot send header after it sent" error.

I don't know what to do since I don't know why the error happened.


Solution

  • I've discovered the error which was that I rapped my async router handler functions with a function called catchAsync()

    module.exports = function (fn) {
      return (req, res, next) => {
        fn(req, res, next).then(next);
      }
    }
    

    I've updated this function to be this

    module.exports = function (fn) {
      return (req, res, next) => {
        try {
          fn(req, res, next);
        } catch (error) {
          next(error);
        }
      };
    };
    

    I made this because the catchAsync function calls the next after the fn() ends which causes to run the next middleware in the stack which is globalErrorHandler

    app.use(globalErrorHandler);
    

    to run and send another response and from here the error happened But what makes me still confused is that the code works fine and then starts throwing errors