hyper-express icon indicating copy to clipboard operation
hyper-express copied to clipboard

Throwing error in Middleware causes app to crash

Open Miggets7 opened this issue 1 month ago • 5 comments

I've got this middleware function:

export async function authJwtMiddleware(req: Request, res: Response, next: MiddlewareNext) {
    const authHeader = req.get("Authorization");
    if (!authHeader) {
        throw new HttpException(401, "No authorization header");
    }

    if (!authHeader.startsWith("Bearer ")) {
        throw new HttpException(401, "Invalid authorization header")
    }

    const token = authHeader.split(" ")[1];
    let session: JWTPayload;
    try {
        session = await DependencyProviderService.getImpl<JwtSessionService>(JwtSessionServiceDi).verifySession(token);
    } catch (err) {
        throw new HttpException(401, err.message);
    }

    req["session"] = session;
    return next();
}

And this error handler:

export function errorMiddleware(
  request: Request,
  response: Response,
  error: Error
) {
  let status = 500;
  if (error instanceof HttpException) {
    status = error.status;
  }
  const message = error.message || "Something went wrong.";

  let data = undefined;
  if (error instanceof ZodError) {
    data = error.errors;
  }

  logger.error(`${status} - ${message} - ${request.originalUrl} - ${request.method} - ${data}: ${error.stack || error.message}`);

  response.status(status).json({ message });
}

The error handler code is called, but still the application crashes:

node:internal/process/promises:289
            triggerUncaughtException(err, true /* fromPromise */);
            ^

HttpException [Error]: No authorization header
    at Object.authJwtMiddleware (/Users/michael/Documents/Projects/Stofloos/rondom-ewd/src/middlewares/auth.middleware.ts:10:15)
    at Route.handle (/Users/michael/Documents/Projects/Stofloos/rondom-ewd/node_modules/hyper-express/src/components/router/Route.js:112:37)
    at iterator (/Users/michael/Documents/Projects/Stofloos/rondom-ewd/node_modules/hyper-express/src/components/router/Route.js:102:22)
    at cors (/Users/michael/Documents/Projects/Stofloos/rondom-ewd/node_modules/cors/lib/index.js:188:7)
    at /Users/michael/Documents/Projects/Stofloos/rondom-ewd/node_modules/cors/lib/index.js:224:17
    at originCallback (/Users/michael/Documents/Projects/Stofloos/rondom-ewd/node_modules/cors/lib/index.js:214:15)
    at /Users/michael/Documents/Projects/Stofloos/rondom-ewd/node_modules/cors/lib/index.js:219:13
    at optionsCallback (/Users/michael/Documents/Projects/Stofloos/rondom-ewd/node_modules/cors/lib/index.js:199:9)
    at Object.corsMiddleware [as handler] (/Users/michael/Documents/Projects/Stofloos/rondom-ewd/node_modules/cors/lib/index.js:204:7)
    at Route.handle (/Users/michael/Documents/Projects/Stofloos/rondom-ewd/node_modules/hyper-express/src/components/router/Route.js:112:37) {
  status: 401
}

It however doesn't crash when writing the middleware like this:

export async function authJwtMiddleware(req: Request, res: Response, next: MiddlewareNext) {
    const authHeader = req.get("Authorization");
    if (!authHeader) {
        return next(new HttpException(401, "No authorization header"));
    }

    if (!authHeader.startsWith("Bearer ")) {
        return next(new HttpException(401, "Invalid authorization header"));
    }

    const token = authHeader.split(" ")[1];
    let session: JWTPayload;
    try {
        session = await DependencyProviderService.getImpl<JwtSessionService>(JwtSessionServiceDi).verifySession(token);
    } catch (err) {
        return next(new HttpException(401, err.message));
    }

    req["session"] = session;
    return next();
}

Is this intended to use return next(error) or is it a bug?

Miggets7 avatar Jun 06 '24 10:06 Miggets7