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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/35088498/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-02 23:43:26  来源:igfitidea点击:

How to get response body in Zuul post filter?

javaproxynetflix-zuul

提问by Dariusz Mydlarz

How it is possible to read a response body while using Zuul as a proxy in postfilter?

post过滤器中使用 Zuul 作为代理时如何读取响应正文?

I am trying to call the code like this:

我正在尝试像这样调用代码:

@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;
    }

}

回答by Dariusz Mydlarz

I've managed to overcome this. The solution consists of 4 steps:

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

  1. Read ctx.getResponseDataStream()into a ByteArrayOutputStream
  2. Copy OutputStream to 2 InputStreams.
  3. Use one of it for your custom purposes.
  4. Use the second to reassign to context: context.setResponseBody(inputStream)
    • reading stream from point 1 would cause that the stream cannot be read again, so this way you're passing a new fresh stream that wasn't read yet
  1. ctx.getResponseDataStream()入 ByteArrayOutputStream
  2. 将 OutputStream 复制到 2 个 InputStreams。
  3. 将其中之一用于您的自定义目的。
  4. 使用第二个重新分配给上下文: context.setResponseBody(inputStream)
    • 从点 1 读取流将导致无法再次读取该流,因此通过这种方式您将传递一个尚未读取的新流

回答by VincentS

If someone is struggling with compressed answer, here's the solution I used:

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

// 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);
}

回答by Pablo Valiente

As you can see in this example, you have two methods available to extract the response body:

正如您在本示例中看到的,您有两种方法可用于提取响应正文:

1- ctx.getResponseBody();

1- ctx.getResponseBody();

2- ctx.getResponseDataStream();

2- ctx.getResponseDataStream();

You have to check which one is not null and use that one.

您必须检查哪个不为空并使用那个。

回答by codesalsa

Thanks for suggestion, this is the code I used that works.

感谢您的建议,这是我使用的有效代码。

try (final InputStream responseDataStream = ctx.getResponseDataStream()) {
   final String responseData = CharStreams.toString(new InputStreamReader(responseDataStream, "UTF-8"));
   ctx.setResponseBody(responseData);
} catch (IOException e) {
   logger.warn("Error reading body",e);
}

回答by Pedro Rom?o

Be careful with the filterNumber

小心 filterNumber

Using anything greater than 1000 leads to an "InputStream already closed" error because the response body has already been read and

使用大于 1000 的任何内容会导致“InputStream 已关闭”错误,因为响应正文已被读取并且

I used the number 10 and worked fine

我使用了数字 10 并且工作正常

回答by Damian

None of the answers worked for me. 1) Order of the filter needs to be lower that 1000 (sending response filter)

没有一个答案对我有用。1) 过滤器的阶数需要低于 1000(发送响应过滤器)

2) Code:

2) 代码:

 private String getResponseData(RequestContext ctx) throws IOException {
    String responseData = null;

    final InputStream responseDataStream = ctx.getResponseDataStream();
    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    ByteArrayOutputStream copy = new ByteArrayOutputStream();
    int read = 0;
    byte[] buff = new byte[1024];
    while ((read = responseDataStream.read(buff)) != -1) {
        bos.write(buff, 0, read);
        copy.write(buff, 0, read);
    }
    InputStream isFromFirstData = new ByteArrayInputStream(bos.toByteArray());

    boolean responseGZipped = ctx.getResponseGZipped();
    try {
        InputStream zin = null;
        if (responseGZipped) {
            zin = new GZIPInputStream(isFromFirstData);
        } else {
            zin = responseDataStream;
        }
        responseData = CharStreams.toString(new InputStreamReader(zin, "UTF-8"));
        ctx.setResponseDataStream(new ByteArrayInputStream(copy.toByteArray()));

    } catch (IOException e) {
        logger.warn("Error reading body {}", e.getMessage());
    }

    return responseData;
}