简体   繁体   中英

How to intercept and edit response body in Zuul post filter?

I am using Zuul post filter to intercept the response. My requirement is to add one new field to response json. I'm able to intercept the response and edit it. But, unable to set the updated response to RequestContext.How it is possible to read a response body ,edit and update it back to RequestContext while using Zuul as a proxy in post filter?

Please find the below code i am using.

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 I am getting is :

Error while sending response to client: java.io.IOException: An existing connection was forcibly closed by the remote host.

Can anyone please help me on this.

I had the same error and got crazy modifying the code described in How to get response body in Zuul post filter? trying different possibilities. Finally I found the solution in this post by writing the answer in the OutputStream from servletResponse.getOutputStream() instead of 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);
}

I had a similar task and tried to do it by writing to the OutputStream. This worked, but had a strange side effect that it made the HttpHeaders in the response to be deleted or corrupted. This made the call produce CORS errors in production even though it ran fine locally through Postman.

I wrote the following method that I call from the run() method of my Post Zuul Filter to add a single node/value to the return 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);
        }
    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM