如何在 Zuul 后置过滤器中拦截和编辑响应正文?
Posted
技术标签:
【中文标题】如何在 Zuul 后置过滤器中拦截和编辑响应正文?【英文标题】:How to intercept and edit response body in Zuul post filter? 【发布时间】:2019-11-06 01:48:00 【问题描述】:我正在使用 Zuul 后置过滤器来拦截响应。我的要求是在响应 json 中添加一个新字段。我能够拦截响应并对其进行编辑。但是,无法将更新的响应设置为 RequestContext。如何在使用 Zuul 作为后置过滤器中的代理时读取响应正文、编辑并将其更新回 RequestContext?
请找到我正在使用的以下代码。
private void updateResponseBody(RequestContext ctx) throws IOException, JSONException
final InputStream responseDataStream = ctx.getResponseDataStream();
String responseData = CharStreams.toString(new InputStreamReader(responseDataStream, "UTF-8"));
JSONObject jsonObj = new JSONObject(responseData);
JSONArray groupsArray = jsonObj.getJSONArray("list");
for (int i = 0; i < groupsArray.length(); i++)
JSONObject groupId = groupsArray.getJSONObject(i);
groupId.accumulate("new_json_field_name", "new_json_field_value");
String updatedResponse = jsonObj.toString();
// ctx.setResponseBody(body); // also not working
ctx.setResponseDataStream(org.apache.commons.io.IOUtils.toInputStream(updatedResponse, "UTF-8"));
我得到的错误是:
Error while sending response to client: java.io.IOException: An existing connection was forcibly closed by the remote host.
谁能帮我解决这个问题。
【问题讨论】:
【参考方案1】:我遇到了同样的错误,并且疯狂地修改How to get response body in Zuul post filter? 中描述的代码尝试不同的可能性。最后我通过在servletResponse.getOutputStream()
而不是ctx.setResponseDataStream()
的OutputStream
中写下答案,在this post中找到了解决方案:
HttpServletResponse servletResponse = ctx.getResponse();
...
String updatedResponse = jsonObj.toString();
try
OutputStream outStream = servletResponse.getOutputStream();
outStream.write(updatedResponse.getBytes(), 0, updatedResponse.length());
outStream.flush();
outStream.close();
catch (IOException e)
log.warn("Error reading body", e);
【讨论】:
【参考方案2】:我有一个类似的任务,并尝试通过写入 OutputStream 来完成。这有效,但有一个奇怪的副作用,它使响应中的 HttpHeaders 被删除或损坏。这使得调用在生产中产生 CORS 错误,即使它通过 Postman 在本地运行良好。
我编写了以下方法,我从 Post Zuul 过滤器的 run() 方法中调用该方法,以将单个节点/值添加到返回 Json。
private void addJsonNode(RequestContext requestContext,String name, String id)
HttpServletResponse servletResponse = requestContext.getResponse();
try
final InputStream responseDataStream = requestContext.getResponseDataStream();
String responseData = CharStreams.toString(new InputStreamReader(responseDataStream, "UTF-8"));
JSONObject jsonObject = new JSONObject(responseData);
jsonObject.put(name, id);
String updatedResponse = jsonObject.toString(4);
requestContext.setResponseBody(updatedResponse);
catch (IOException e)
log.warn("Error reading body", e);
catch (JSONException e)
log.warn("Error reading body", e);
【讨论】:
以上是关于如何在 Zuul 后置过滤器中拦截和编辑响应正文?的主要内容,如果未能解决你的问题,请参考以下文章
(34)java Spring Cloud+Spring boot+mybatis企业快速开发架构之SpringCloud-Zuul过滤器介绍及使用(传递数据拦截请求和异常处理)