Ashish Vasikaran
Ashish Vasikaran

Reputation: 11

Servlet Response filter does not modify response body for successful request (200 OK), works well for exception

I have a servlet response filter. My response body is not modified for successful requests. Exceptions are successful wrapped and response body is modified. My code is mere copy/paste from the book O'Reilly Learning Java 4th edition code found at https://learning.oreilly.com/library/view/learning-java-4th/9781449372477/ch15s04.html#:-:text=Filtering%20the%20Servlet%20Response

Here is the code from the book with minor modifications for my requirement-

public class LinkResponseFilter implements Filter {
    FilterConfig filterConfig;
    public void init(FilterConfig filterConfig) {
        this.filterConfig = filterConfig;
    }
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
        WrappedResponse wrappedResponse = new WrappedResponse((HttpServletResponse) res);
        chain.doFilter(req, wrappedResponse);
        wrappedResponse.close();
    }
    public void destroy() {
    }
    static class WrappedResponse extends HttpServletResponseWrapper {
        boolean linkText;
        PrintWriter client;
        WrappedResponse(HttpServletResponse res) {
            super(res);
        }
        public void setContentType(String mime) {
            super.setContentType(mime);
            if (mime.startsWith("application/fhir+json")) {   //BOOK CODE CHECKS FOR html
                linkText = true;
            }
        }
        public PrintWriter getWriter() throws IOException {
            if (client == null) {
                if (linkText) {
                    client = new LinkWriter(super.getWriter(), new ByteArrayOutputStream());
                } else {
                    client = super.getWriter();
                }
            }
            return client;
        }
        void close() {
            if (client != null) {
                client.close();
            }
        }
    }
    static class LinkWriter extends PrintWriter {
        ByteArrayOutputStream buffer;
        Writer client;
        LinkWriter(Writer client, ByteArrayOutputStream buffer) {
            super(buffer);
            this.buffer = buffer;
            this.client = client;
        }
        public void close() {
            try {
                flush();
                client.write(linkText(buffer.toString()));
                client.close();
            } catch (IOException e) {
                setError();
            }
        }
        String  linkText(String text) {
            text = text.replaceAll( "resourceType", "None");//BOOK HAS DIFFERENT LOGIC
            return text;
        }
    }
}

Upvotes: 0

Views: 136

Answers (1)

Mohamed Ismail M
Mohamed Ismail M

Reputation: 100

From the book itself it clearly mentioned

That was a bit longer than our previous examples, but the basics are the same. We wrapped the HttpServletResponse object with our own WrappedResponse class using the HttpServletResponseWrapper helper class. Our WrappedResponse overrides two methods: getWriter() and setContentType(). We override setContentType() in order to set a flag that indicates whether the output is of type “text/html” (an HTML document). We don’t want to be performing regular-expression replacements on binary data such as images, for example, should they happen to match our filter. We also override getWriter() to provide our substitute writer stream, LinkWriter. Our LinkWriter class is a PrintStream that takes as arguments the client PrintWriter and a ByteArrayOutputStream that serves as a buffer for storing output data before it is written. We are careful to substitute our LinkWriter only if the linkText Boolean set by setContent() is true. When we do use our LinkWriter, we cache the stream so that any subsequent calls to getWriter() return the same object. Finally, we have added one method to the response object: close(). A normal HttpServletResponse does not have a close() method. We use ours on the return trip to the client to indicate that the LinkWriter should complete its processing and write the actual data to the client. We do this in case the client does not explicitly close the output stream before exiting the servlet service methods.

which means when we set the linkText = true for the contentType "application/fhir+json" then the getWriter() method will return the same object which means the WrappedResponse will not happen to the successful responses which has the contentType "application/fhir+json".

As I asked previously have you gone through the debug mode for successful and failure .

  1. is the flag set to true for failure exception also ?
  2. Do you have any other Filter Configuration
  3. linkText is the culprit in your case . Do the debug and you will came to a conclusion

Upvotes: 0

Related Questions