diff --git a/packages/common/interfaces/http/http-server.interface.ts b/packages/common/interfaces/http/http-server.interface.ts index b85595c41e2..9d91a97ff3b 100644 --- a/packages/common/interfaces/http/http-server.interface.ts +++ b/packages/common/interfaces/http/http-server.interface.ts @@ -50,8 +50,10 @@ export interface HttpServer { listen(port: number | string, hostname: string, callback?: () => void): any; reply(response: any, body: any, statusCode?: number): any; status(response: any, statusCode: number): any; + end(response: any, message?: string): any; render(response: any, view: string, options: any): any; redirect(response: any, statusCode: number, url: string): any; + isHeadersSent(response: any): boolean; setHeader(response: any, name: string, value: string): any; setErrorHandler?(handler: Function, prefix?: string): any; setNotFoundHandler?(handler: Function, prefix?: string): any; diff --git a/packages/core/adapters/http-adapter.ts b/packages/core/adapters/http-adapter.ts index b5379933aeb..c5d778c1345 100644 --- a/packages/core/adapters/http-adapter.ts +++ b/packages/core/adapters/http-adapter.ts @@ -105,10 +105,12 @@ export abstract class AbstractHttpAdapter< abstract getRequestUrl(request); abstract status(response, statusCode: number); abstract reply(response, body: any, statusCode?: number); + abstract end(response, message?: string); abstract render(response, view: string, options: any); abstract redirect(response, statusCode: number, url: string); abstract setErrorHandler(handler: Function, prefix?: string); abstract setNotFoundHandler(handler: Function, prefix?: string); + abstract isHeadersSent(response); abstract setHeader(response, name: string, value: string); abstract registerParserMiddleware(prefix?: string); abstract enableCors( diff --git a/packages/core/exceptions/base-exception-filter.ts b/packages/core/exceptions/base-exception-filter.ts index ea360e84a69..bc378450120 100644 --- a/packages/core/exceptions/base-exception-filter.ts +++ b/packages/core/exceptions/base-exception-filter.ts @@ -38,7 +38,12 @@ export class BaseExceptionFilter implements ExceptionFilter { message: res, }; - applicationRef.reply(host.getArgByIndex(1), message, exception.getStatus()); + const response = host.getArgByIndex(1); + if (!applicationRef.isHeadersSent(response)) { + applicationRef.reply(response, message, exception.getStatus()); + } else { + applicationRef.end(response); + } } public handleUnknownError( @@ -55,7 +60,14 @@ export class BaseExceptionFilter implements ExceptionFilter { statusCode: HttpStatus.INTERNAL_SERVER_ERROR, message: MESSAGES.UNKNOWN_EXCEPTION_MESSAGE, }; - applicationRef.reply(host.getArgByIndex(1), body, body.statusCode); + + const response = host.getArgByIndex(1); + if (!applicationRef.isHeadersSent(response)) { + applicationRef.reply(response, body, body.statusCode); + } else { + applicationRef.end(response); + } + if (this.isExceptionObject(exception)) { return BaseExceptionFilter.logger.error( exception.message, diff --git a/packages/core/test/utils/noop-adapter.spec.ts b/packages/core/test/utils/noop-adapter.spec.ts index c2e73d09fd6..67eafa54e09 100644 --- a/packages/core/test/utils/noop-adapter.spec.ts +++ b/packages/core/test/utils/noop-adapter.spec.ts @@ -13,11 +13,13 @@ export class NoopHttpAdapter extends AbstractHttpAdapter { getRequestMethod(request: any): any {} getRequestUrl(request: any): any {} reply(response: any, body: any): any {} + end(response: any, message?: any): any {} status(response: any, statusCode: number): any {} render(response: any, view: string, options: any): any {} redirect(response: any, statusCode: number, url: string) {} setErrorHandler(handler: Function, prefix = '/'): any {} setNotFoundHandler(handler: Function, prefix = '/'): any {} + isHeadersSent(response: any): any {} setHeader(response: any, name: string, value: string): any {} registerParserMiddleware(): any {} enableCors(options: any): any {} diff --git a/packages/platform-express/adapters/express-adapter.ts b/packages/platform-express/adapters/express-adapter.ts index bb2ae7337cb..4717a3e8f68 100644 --- a/packages/platform-express/adapters/express-adapter.ts +++ b/packages/platform-express/adapters/express-adapter.ts @@ -60,6 +60,10 @@ export class ExpressAdapter extends AbstractHttpAdapter { return response.status(statusCode); } + public end(response: any, message?: string) { + return response.end(message); + } + public render(response: any, view: string, options: any) { return response.render(view, options); } @@ -76,6 +80,10 @@ export class ExpressAdapter extends AbstractHttpAdapter { return this.use(handler); } + public isHeadersSent(response: any): boolean { + return response.headersSent; + } + public setHeader(response: any, name: string, value: string) { return response.set(name, value); } diff --git a/packages/platform-fastify/adapters/fastify-adapter.ts b/packages/platform-fastify/adapters/fastify-adapter.ts index 77ac6ae1619..4ac3f72ee57 100644 --- a/packages/platform-fastify/adapters/fastify-adapter.ts +++ b/packages/platform-fastify/adapters/fastify-adapter.ts @@ -300,6 +300,10 @@ export class FastifyAdapter< return (response as TReply).code(statusCode); } + public end(response: TReply, message?: string) { + response.raw.end(message); + } + public render( response: TReply & { view: Function }, view: string, @@ -384,6 +388,10 @@ export class FastifyAdapter< ); } + public isHeadersSent(response: TReply): boolean { + return response.sent; + } + public setHeader(response: TReply, name: string, value: string) { return response.header(name, value); }