You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在NestJS中通过NestInterceptor在响应发送给客户端前记录响应数据

问题

enter image description here

目前我只能检查Request对象,无法查看Controller发送的Response对象。

我可以从Response中获取以下属性:

  • statusCode
  • statusMessage
    等等

如何在响应发送给客户端前追踪响应体?

解决方案

要在响应发送给客户端前追踪响应体,核心思路是包装Response对象,通过自定义响应包装器捕获输出流中的内容,下面以Spring MVC为例给出具体实现:

1. 自定义响应包装器类

继承HttpServletResponseWrapper,重写输出流相关方法,将响应内容暂存到字节数组中:

public class ResponseWrapper extends HttpServletResponseWrapper {
    private final ByteArrayOutputStream byteArrayOutputStream;
    private ServletOutputStream servletOutputStream;
    private PrintWriter printWriter;

    public ResponseWrapper(HttpServletResponse response) throws IOException {
        super(response);
        byteArrayOutputStream = new ByteArrayOutputStream();
    }

    @Override
    public ServletOutputStream getOutputStream() throws IOException {
        if (servletOutputStream == null) {
            servletOutputStream = new DelegatingServletOutputStream(byteArrayOutputStream);
        }
        return servletOutputStream;
    }

    @Override
    public PrintWriter getWriter() throws IOException {
        if (printWriter == null) {
            printWriter = new PrintWriter(new OutputStreamWriter(byteArrayOutputStream, getCharacterEncoding()));
        }
        return printWriter;
    }

    @Override
    public void flushBuffer() throws IOException {
        if (servletOutputStream != null) {
            servletOutputStream.flush();
        }
        if (printWriter != null) {
            printWriter.flush();
        }
        super.flushBuffer();
    }

    // 获取捕获到的响应体字符串
    public String getResponseBody() throws IOException {
        flushBuffer();
        return byteArrayOutputStream.toString(getCharacterEncoding());
    }
}

2. 自定义过滤器拦截请求

创建过滤器替换原生Response为自定义包装器,在响应处理完成后读取并处理响应体:

@Component
public class ResponseLoggingFilter implements Filter {
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        ResponseWrapper responseWrapper = new ResponseWrapper((HttpServletResponse) response);
        // 继续执行请求链,Controller会将响应写入包装器
        chain.doFilter(request, responseWrapper);
        
        // 此处获取响应体,可根据需求打印、存储或分析
        String responseBody = responseWrapper.getResponseBody();
        System.out.println("捕获到的响应体:" + responseBody);
        
        // 将暂存的响应内容写回原生响应,确保客户端能正常接收
        ServletOutputStream outputStream = response.getOutputStream();
        outputStream.write(responseBody.getBytes(responseWrapper.getCharacterEncoding()));
        outputStream.flush();
    }
}

3. 注册过滤器(按需配置)

若未通过@Component自动注册,可通过配置类手动注册并指定拦截路径:

@Configuration
public class FilterConfig {
    @Bean
    public FilterRegistrationBean<ResponseLoggingFilter> responseLoggingFilterRegistration() {
        FilterRegistrationBean<ResponseLoggingFilter> registrationBean = new FilterRegistrationBean<>();
        registrationBean.setFilter(new ResponseLoggingFilter());
        registrationBean.addUrlPatterns("/*"); // 拦截所有请求路径
        return registrationBean;
    }
}

如果是其他Web框架(如纯Servlet、Spring Boot等),核心逻辑一致:通过包装响应对象捕获输出流,在响应提交前读取内容,再将内容写回原响应保证客户端正常接收。


内容的提问来源于stack exchange,提问作者Rohit Sengar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 12:07:47