NestJS拦截器提前返回数据触发[ERR_HTTP_HEADERS_SENT]错误如何解决
问题原因
你触发ERR_HTTP_HEADERS_SENT错误的核心原因是:在拦截器中直接调用原生响应对象的send方法返回内容后,没有告知NestJS框架无需再处理本次请求的响应链路,框架后续仍会自动执行响应头设置、内容发送的逻辑,尝试对已经结束的响应对象做操作,就触发了该错误。
Postman请求未触发报错是偶发现象,是因为Postman请求的场景下,框架后续自动执行的逻辑刚好没有需要新增/修改的响应头,没有触发冲突,本质上问题一直存在。
解决方案
方案1(推荐,符合NestJS最佳实践)
不要直接操作原生响应对象,直接返回包装了模拟数据的Observable即可,由NestJS统一处理响应发送,完全规避响应冲突问题,也能适配你项目中配置的全局序列化、异常过滤器等逻辑:
import { Injectable, NestInterceptor, ExecutionContext, CallHandler } from '@nestjs/common'; import { Observable, of } from 'rxjs'; @Injectable() export class UserPageStatsInterceptor implements NestInterceptor { intercept(context: ExecutionContext, next: CallHandler): Observable<any> { if (!isDemo(context)) { return next.handle(); } // 直接返回模拟数据,由框架处理响应发送 return of('Demo data'); } }
方案2(需要手动操作原生响应对象时使用)
如果你的场景必须要手动调用原生响应对象的方法发送内容,只需要在发送完成后返回rxjs的EMPTY对象,告知框架无需再处理本次响应即可:
import { Injectable, NestInterceptor, ExecutionContext, CallHandler } from '@nestjs/common'; import { Observable, EMPTY } from 'rxjs'; @Injectable() export class UserPageStatsInterceptor implements NestInterceptor { intercept(context: ExecutionContext, next: CallHandler): Observable<any> { if (!isDemo(context)) { return next.handle(); } const res = context.switchToHttp().getResponse(); res.status(200).send('Demo data'); // 告知框架响应已处理完成,无需后续操作 return EMPTY; } }
内容的提问来源于stack exchange,提问作者user16973736
相关产品推荐
相关产品推荐

