0

I am working on a spring boot application. I want to modify the response of the request by request body field "Id".

I have implemented below, but still getting just the name in the output while implementing.Any suggestions on implementing below would be helpful:

Below is the requestBody:

{
"id" : "123"
}

In response, I want to append that field to response id(fieldname from request body). responseBody:

{
"name" : "foo123"  //name + id from request
}

MyCustomFilter:

public class TestFilter implements Filter {


    @Override
    public void doFilter(
            ServletRequest request,
            ServletResponse response,
            FilterChain chain) throws IOException, ServletException {
       HttpServletResponse res = (HttpServletResponse) response;
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    final PrintStream ps = new PrintStream(baos);
    MultiReadHttpServletRequest wrapper = new MultiReadHttpServletRequest((HttpServletRequest) request);

    MyRequestWrapper req = new MyRequestWrapper(wrapper);
    String userId = req.getId();

    chain.doFilter(wrapper, new HttpServletResponseWrapper(res) {
        @Override
        public ServletOutputStream getOutputStream() throws IOException {
            return new DelegatingServletOutputStream(new TeeOutputStream(super.getOutputStream(), ps)
            );
        }

        @Override
        public PrintWriter getWriter() throws IOException {
            return new PrintWriter(new DelegatingServletOutputStream(new TeeOutputStream(super.getOutputStream(), ps))
            );
        }
    });

    String responseBody = baos.toString();

    ObjectMapper mapper = new ObjectMapper();
    JsonNode node = mapper.readTree(responseBody);
    String name = node.get("name").astext();

    ((ObjectNode) node1).put("name", name + userId);

    chain.doFilter(wrapper, res);
}

MyRequestWrapper:

public class MyRequestWrapper extends HttpServletRequestWrapper {
    private ServletInputStream input;

    public MyRequestWrapper(ServletRequest request) {
        super((HttpServletRequest)request);
    }

    public String getId() throws IOException {
        if (input == null) {
            try {
                JSONObject jsonObject = new JSONObject(IOUtils.toString(super.getInputStream()));
                String userId = jsonObject.getString("id");

                userId = userId.replaceAll("\\D+","");
                return userId;
            } catch (JSONException e) {
                e.printStackTrace();
            }
        }
        return null;
    }
}

MultiReadHttpServletRequest.java

public class MultiReadHttpServletRequest extends HttpServletRequestWrapper {

private byte[] body;

public MultiReadHttpServletRequest(HttpServletRequest request) {
    super(request);
    try {
        body = IOUtils.toByteArray(request.getInputStream());
    } catch (IOException ex) {
        body = new byte[0];
    }
}

@Override
public BufferedReader getReader() throws IOException {
    return new BufferedReader(new InputStreamReader(getInputStream(), getCharacterEncoding()));
}

@Override
public ServletInputStream getInputStream() throws IOException {
    return new ServletInputStream() {
        ByteArrayInputStream wrapperStream = new ByteArrayInputStream(body);

        @Override
        public boolean isFinished() {
            return false;
        }

        @Override
        public boolean isReady() {
            return false;
        }

        @Override
        public void setReadListener(ReadListener readListener) {

        }

        @Override
        public int read() throws IOException {
            return wrapperStream.read();
        }
    };
}

}

Any suggestions are appreciated. TIA. Nte: After update i am not able to see the updated response as output. I am still seeing just the name but not id appended to it.

ging
  • 219
  • 7
  • 20
  • This will not be valid JSON "foo"+"123" – Simon Martinelli Apr 28 '20 at 08:01
  • @SimonMartinelli updated the question. I mean to say concatenate together in the response. Any suggestions on this please? – ging Apr 28 '20 at 08:04
  • Just pass your own implementation of request/response into filter chain: `chain.doFilter(req /*MyRequestWrapper*/, res);`. Or try to put your code just after chain.doFilter(). Check [this](https://stackoverflow.com/questions/25020331/spring-mvc-how-to-modify-json-response-sent-from-controller). – slesh Apr 28 '20 at 08:05
  • @slesh updated the question. Actually i am not seeing the modifed response in the output. Any suggestions please> – ging Apr 28 '20 at 08:27

1 Answers1

0

The one issue I see with your own implementation of ServletRequest is that you call super.getInputStream() instead of request.getInputStream(). Your own request is empty by default, that's why you're getting time out exception. You have to delegate a call to the actual request:

public class MyRequestWrapper extends HttpServletRequestWrapper {
    private ServletInputStream input;

    public MyRequestWrapper(ServletRequest request) {
        super((HttpServletRequest)request);
    }

    public String getId() throws IOException {
        if (input == null) {
            try {
                JSONObject jsonObject = new JSONObject(IOUtils.toString(/*DELETEGATE TO ACTUAL REQUEST*/request.getInputStream()));
                String userId = jsonObject.getString("id");

                userId = userId.replaceAll("\\D+","");
                return userId;
            } catch (JSONException e) {
                e.printStackTrace();
            }
        }
        return null;
    }
}
slesh
  • 1,902
  • 1
  • 18
  • 29
  • Actually i just tried MultiReadHttpServletRequest (Updated in question). But still i am getting the original response. But not the updated response. – ging Apr 28 '20 at 08:17