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
How to get response body in Zuul post filter?
提问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个步骤:
- Read
ctx.getResponseDataStream()into a ByteArrayOutputStream - Copy OutputStream to 2 InputStreams.
- Use one of it for your custom purposes.
- 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
- 读
ctx.getResponseDataStream()入 ByteArrayOutputStream - 将 OutputStream 复制到 2 个 InputStreams。
- 将其中之一用于您的自定义目的。
- 使用第二个重新分配给上下文:
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;
}

