J'essaie d'utiliser un ExceptionFilter
pour mapper des exceptions à leur contrepartie HTTP.
Ceci est mon code:
@Catch(EntityNotFoundError)
export class EntityNotFoundFilter implements ExceptionFilter {
catch(exception: EntityNotFoundError, _Host: ArgumentsHost) {
throw new NotFoundException(exception.message);
}
}
Mais, lorsque le code de filtre est exécuté, j'ai reçu un UnhandledPromiseRejectionWarning
(node:3065) UnhandledPromiseRejectionWarning: Error: [object Object]
at EntityNotFoundFilter.catch ([...]/errors.ts:32:15)
at ExceptionsHandler.invokeCustomFilters ([...]/node_modules/@nestjs/core/exceptions/exceptions-handler.js:49:26)
at ExceptionsHandler.next ([...]/node_modules/@nestjs/core/exceptions/exceptions-handler.js:13:18)
at [...]/node_modules/@nestjs/core/router/router-proxy.js:12:35
at <anonymous>
at process._tickCallback (internal/process/next_tick.js:182:7)
(node:3065) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 5)
Comment puis-je réparer cela ?
Le ExceptionFilter
est toujours le dernier endroit qui est appelé avant qu'une réponse soit envoyée, il est responsable de la construction de la réponse. Vous ne pouvez pas réthorner une exception de l'intermédiaire d'un ExceptionFilter
.
@Catch(EntityNotFoundError)
export class EntityNotFoundFilter implements ExceptionFilter {
catch(exception: EntityNotFoundError, Host: ArgumentsHost) {
const response = Host.switchToHttp().getResponse();
response.status(404).json({ message: exception.message });
}
}
Sinon, vous pouvez créer un Interceptor
qui transforme vos erreurs:
@Injectable()
export class NotFoundInterceptor implements NestInterceptor {
intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
// next.handle() is an Observable of the controller's result value
return next.handle()
.pipe(catchError(error => {
if (error instanceof EntityNotFoundError) {
throw new NotFoundException(error.message);
} else {
throw error;
}
}));
}
}
Essayez-le dans ce codesandbox .
Base sur la solution Kim Kern que j'ai créé cette classe abstraite
export abstract class AbstractErrorInterceptor<T> implements NestInterceptor {
protected interceptedType: new (...args) => T;
intercept(
context: ExecutionContext,
call$: Observable<any>,
): Observable<any> | Promise<Observable<any>> {
return call$.pipe(
catchError(exception => {
if (exception instanceof this.interceptedType) {
this.handleError(exception);
}
throw exception;
}),
);
}
abstract handleError(exception: T);
}
Et certaines implémentations
export class EntityNotFoundFilter extends AbstractErrorInterceptor<EntityNotFoundError> {
interceptedType = EntityNotFoundError;
handleError(exception: EntityNotFoundError) {
throw new NotFoundException(exception.message);
}
}