如何在Zuul后置过滤器中获取响应体?

2022-09-03 17:34:19

如何在使用 Zuul 作为筛选器中的代理时读取响应正文?post

我试图像这样调用代码:

@Component
public class PostFilter extends ZuulFilter {

    private static final Logger log = LoggerFactory.getLogger(PostFilter.class);

    @Override
    public String filterType() {
        return "post";
    }

    @Override
    public int filterOrder() {
        return 2000;
    }

    @Override
    public boolean shouldFilter() {
        return true;
    }

    @Override
    public Object run() {
        RequestContext ctx = RequestContext.getCurrentContext();
        ctx.getResponseBody(); // null

        // cant't do this, cause input stream is used later in other filters and I got InputStream Closed exception
        // GZIPInputStream gzipInputStream = new GZIPInputStream(stream);
        return null;
    }

}

答案 1

我已经设法克服了这一点。该解决方案包括 4 个步骤:

  1. 读入 ByteArrayOutputStreamctx.getResponseDataStream()
  2. 将输出流复制到 2 个输入流。
  3. 将其之一用于自定义目的。
  4. 使用第二个重新分配给上下文:context.setResponseBody(inputStream)
    • 从第 1 点读取流将导致无法再次读取流,因此通过这种方式,您将传递尚未读取的新流

答案 2

如果有人正在为压缩答案而苦苦挣扎,这是我使用的解决方案:

// Read the compressed response
RequestContext ctx = RequestContext.getCurrentContext();
InputStream compressedResponseDataStream = ctx.getResponseDataStream();
try {
    // Uncompress and transform the response
    InputStream responseDataStream = new GZIPInputStream(compressedResponseDataStream);
    String responseAsString = StreamUtils.copyToString(responseDataStream, Charset.forName("UTF-8"));
    // Do want you want with your String response
    ...
    // Replace the response with the modified object
    ctx.setResponseBody(responseAsString);
} catch (IOException e) {
    logger.warn("Error reading body", e);
}

推荐