Routing-controllers: how to catch 404 http error when defaultErrorHandler=false

Created on 17 Oct 2017  路  6Comments  路  Source: typestack/routing-controllers

I write an custom ErrorHandle implements ExpressErrorMiddlewareInterface but cannot catch 404 error.

awaiting answer question

Most helpful comment

You can put this as the last middleware:

import { Middleware, ExpressMiddlewareInterface } from 'routing-controllers';
import { NextFunction, Request, Response } from 'express';
import * as debug from 'debug';

import { NotFoundError } from '../errors/notfound.error';

@Middleware({ type: 'after' })
export class FinalMiddleware implements ExpressMiddlewareInterface {
  private logger: debug.IDebugger = debug('project:middleware:FinalMiddleware');

  public use(req: Request, res: Response, next?: NextFunction): void {
    this.logger('FinalMiddleware reached, ending response.');
    if(!res.headersSent) {
      // TODO: match current url against every registered one
      // because finalhandler is reached if no value is returned in the controller.
      // so we need to set 404 only if really there are no path handling this.
      // or we just have to return with null?
      res.status(404);
      res.send(new NotFoundError({ id: req.path, type: 'route' }));
    }
    res.end();
  }

}
// ...
middlewares: [
  CorsMiddleware,
  FinalMiddleware,
  ErrorHandlerMiddleware,
],
// ...

All 6 comments

Because when there's no route matching the request url, it's just go out of routing-controllers stack, which behave like a big express/koa middleware. So the express/koa final handler catch no matching route, create 404 error and the default express/koa error handler return it in response.

So you should not only write custom error middleware but also custom after middleware with low priority which would behave like a guard that all request, even when no matching route has been found, will be called.

How would i know if a route was matched or not? When i write the custom after middleware it gets always called, even if a route was matched.

You can put this as the last middleware:

import { Middleware, ExpressMiddlewareInterface } from 'routing-controllers';
import { NextFunction, Request, Response } from 'express';
import * as debug from 'debug';

import { NotFoundError } from '../errors/notfound.error';

@Middleware({ type: 'after' })
export class FinalMiddleware implements ExpressMiddlewareInterface {
  private logger: debug.IDebugger = debug('project:middleware:FinalMiddleware');

  public use(req: Request, res: Response, next?: NextFunction): void {
    this.logger('FinalMiddleware reached, ending response.');
    if(!res.headersSent) {
      // TODO: match current url against every registered one
      // because finalhandler is reached if no value is returned in the controller.
      // so we need to set 404 only if really there are no path handling this.
      // or we just have to return with null?
      res.status(404);
      res.send(new NotFoundError({ id: req.path, type: 'route' }));
    }
    res.end();
  }

}
// ...
middlewares: [
  CorsMiddleware,
  FinalMiddleware,
  ErrorHandlerMiddleware,
],
// ...

Will try this out, res.headersSent seems to be what i was looking for to determin if a response was sent

Stale issue message

This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

posabsolute picture posabsolute  路  4Comments

AleskiWeb picture AleskiWeb  路  4Comments

iangregsondev picture iangregsondev  路  3Comments

ghost picture ghost  路  5Comments

szabobar picture szabobar  路  4Comments