【问题标题】:How to intercept and edit response body in Zuul post filter?如何在 Zuul 后置过滤器中拦截和编辑响应正文?
【发布时间】: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.

谁能帮我解决这个问题。

【问题讨论】:

    标签: java spring-boot proxy netflix-zuul


    【解决方案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);
              }
          }
      

      【讨论】:

        猜你喜欢
        • 2016-05-07
        • 1970-01-01
        • 2011-04-24
        • 2012-06-22
        • 1970-01-01
        • 2020-08-30
        • 1970-01-01
        • 2019-07-08
        • 2016-10-14
        相关资源
        最近更新 更多