routing-controllers
routing-controllers copied to clipboard
fix: Default error handler doesn't work with express session/useExpressServer
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
- Call the endpoint hosted on
/
- Receive JSON response:
{
"name": "HttpError",
"message": "whoops",
"stack": "Error: \n at new HttpError..."
}
Actual behavior
- Call the endpoint hosted on
/
- Node crashes with a series of the HTTPError objects logged to the console (10 times to be specific)
@jddunleavy Have you tried to start your application with production mode?
NODE_ENV=production npm run start
I am also experiencing this problem and have tried starting the application in production mode. Any ideas what this could be?
@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 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);