如何在Zuul帖子过滤器中拦截和编辑响应正文?

时间:2019-06-24 09:17:54

标签: java spring-boot proxy netflix-zuul

我正在使用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.

有人可以帮我吗?

2 个答案:

答案 0 :(得分:0)

我遇到了同样的错误,并且疯狂地尝试修改How to get response body in Zuul post filter?中描述的代码,尝试了不同的可能性。最后,我在this post中找到了解决方案,方法是将答案写在OutputStream中的servletResponse.getOutputStream()中,而不是ctx.setResponseDataStream()中:

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

答案 1 :(得分:0)

我有一个类似的任务,并尝试通过写入OutputStream来完成。这行得通,但是有一个奇怪的副作用,它使响应中的HttpHeaders被删除或损坏。即使通过Postman在本地运行良好,这也使该调用在生产中产生CORS错误。

我编写了以下方法,从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);
        }
    }