routing-controllers icon indicating copy to clipboard operation
routing-controllers copied to clipboard

fix: Default error handler doesn't work with express session/useExpressServer

Open jddunleavy opened this issue 3 years ago • 4 comments

Description

When attempting to use express-session for session management (with the intention of making use of the @Session decorator) Errors thrown within routes are no longer being handled by the default error handler. In the code snippet below when I remove express-session the error gets returned correctly to the caller, but with the session configured the node process crashes with the throw HTTPError.

As an aside I would say there's very little documentation on how I'm supposed to configure sessions with Routing-controllers, so there's a reasonable chance this isn't the intended/supported way. Given the mention of express-session in the documentation I assume this is the supported express session manager!

Minimal code-snippet showcasing the problem

import express from "express";
import session from "express-session";
import {
  Get,
  HttpError,
  JsonController,
  useExpressServer,
} from "routing-controllers";

@JsonController()
class MainController {
  @Get("/")
  get() {
    throw new HttpError(500, "whoops");
  }

  // Curiously when the controller has only one route this issue
  // doesn't occur
  @Get("/another")
  getAnother() {
    return "another";
  }
}

const app = express();

// Commenting out this block makes it work again
app.use(
  session({
    secret: "23ruhiw",
    resave: true,
    saveUninitialized: true,
  })
);

useExpressServer(app, {
  controllers: [MainController],
});

app.listen(5000);

Expected behavior

  1. Call the endpoint hosted on /
  2. Receive JSON response:
{
  "name": "HttpError",
  "message": "whoops",
  "stack": "Error: \n    at new HttpError..."
}

Actual behavior

  1. Call the endpoint hosted on /
  2. Node crashes with a series of the HTTPError objects logged to the console (10 times to be specific)

jddunleavy avatar Feb 01 '21 16:02 jddunleavy

@jddunleavy Have you tried to start your application with production mode? NODE_ENV=production npm run start

shad0w-jo4n avatar Feb 16 '21 21:02 shad0w-jo4n

I am also experiencing this problem and have tried starting the application in production mode. Any ideas what this could be?

wpf500 avatar Jun 30 '21 13:06 wpf500

@wpf500 It is a problem of the execution chain unfortunately. Could you try to register a custom error handler to see if that solves your problem? https://github.com/typestack/routing-controllers#error-handlers

attilaorosz avatar Feb 18 '22 16:02 attilaorosz

@attilaorosz that's what we ended up doing :+1:.

For reference our solution looks vaguely as shown below, although I've just pasted in the relevant bits so this code is just an example. I haven't done extensive testing on the error handling but it seems to work for us :smile:

const app = express();

app.use(session());

useExpressServer(app, {
  // ...other options,
  defaultErrorHandler: false
});

app.use((req, res) => {
  if (!res.headersSent) {
    throw new NotFoundError();
  }
});

app.use(function (error, req, res, next) {
  if (error instanceof HttpError) {
    res.status(error.httpCode).send(error);
  } else {
    res.status(500).send(new InternalServerError("Unhandled error"));
  }
} as ErrorRequestHandler);

wpf500 avatar Mar 03 '22 10:03 wpf500