[英]How to get response body in Zuul post filter?
How it is possible to read a response body while using Zuul as a proxy in post
filter?在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;
}
}
I've managed to overcome this.我已经设法克服了这一点。 The solution consists of 4 steps:解决方案包括 4 个步骤:
ctx.getResponseDataStream()
into a ByteArrayOutputStream ctx.getResponseDataStream()
读入 ByteArrayOutputStreamcontext.setResponseBody(inputStream)
使用第二个重新分配给上下文: context.setResponseBody(inputStream)
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);
}
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);
}
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.您必须检查哪一个不为空并使用那个。
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 并且工作正常
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;
}
The simplest solution would be to get an input stream, read it with InputStreamReader
, and finally create a new stream based on the read string and set it as a response data stream of context.最简单的解决方案是获取一个输入流,使用InputStreamReader
读取它,最后根据读取的字符串创建一个新流并将其设置为上下文的响应数据流。 Also, don't forget to set the order of the filter to number lower then 1000.另外,不要忘记将过滤器的顺序设置为低于 1000 的数字。
final InputStream responseDataStream = ctx.getResponseDataStream();
String response = CharStreams.toString(new InputStreamReader(responseDataStream, StandardCharsets.UTF_8));
InputStream stream = new ByteArrayInputStream(response.getBytes(StandardCharsets.UTF_8));
ctx.setResponseDataStream(stream);
//NOTE:filterOrder:999
RequestContext context = getCurrentContext();
InputStream stream = context.getResponseDataStream();
// uncompress
String body = StreamUtils.copyToString(new GZIPInputStream(stream),
Charset.forName("UTF-8"));
// modify
body = "Modified gzipped response via setResponseBody(): " + body;
// compress again
ByteArrayOutputStream bos = new ByteArrayOutputStream(body.length());
GZIPOutputStream gzip = new GZIPOutputStream(bos);
gzip.write(body.getBytes("UTF-8"));
gzip.close();
byte[] compressed = bos.toByteArray();
bos.close();
context.setResponseDataStream(new ByteArrayInputStream(compressed));
https://github.com/spring-attic/sample-zuul-filters/issues/4https://github.com/spring-attic/sample-zuul-filters/issues/4
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.