I've been searching the net and stackoverflow for an example of somebody inserting content into the response using a servlet filter, but can only find examples of people capturing/compressing the output and/or changing the headers. My goal is to append a chunk of HTML just before the closing </body> of all HTML responses.
I'm working on a solution that extends the HttpServletResponseWrapper to use my own PrintWriter, then overriding the write methods thereon. Inside the write method I'm storing the last 7 characters to see if it's equal to the closing body tag, and then I write my HTML chunk plus the closing body tag, before continuing normal write operations for the rest of the document.
I feel that somebody must have solved this problem already, and probably more elegantly than I will. I'd appreciate any examples of how to use a servlet filter to insert content into a response.
UPDATED
Responding to a comment, I am also trying to implement the CharResponseWrapper from http://www.oracle.com/technetwork/java/filters-137243.html. Here is my code:
PrintWriter out = response.getWriter(); CharResponseWrapper wrappedResponse = new CharResponseWrapper( (HttpServletResponse)response); chain.doFilter(wrappedRequest, wrappedResponse); String s = wrappedResponse.toString(); if (wrappedResponse.getContentType().equals("text/html") && StringUtils.isNotBlank(s)) { CharArrayWriter caw = new CharArrayWriter(); caw.write(s.substring(0, s.indexOf("</body>") - 1)); caw.write("WTF</body></html>"); response.setContentLength(caw.toString().length()); out.write(caw.toString()); } else { out.write(wrappedResponse.toString()); } out.close();
I am also wrapping the request, but that code works and shouldn't affect the response.
A filter is an object that is invoked at the preprocessing and postprocessing of a request. It is mainly used to perform filtering tasks such as conversion, logging, compression, encryption and decryption, input validation etc. The servlet filter is pluggable, i.e. its entry is defined in the web.
A filter is an object that can transform the header and content (or both) of a request or response. Filters differ from web components in that filters usually do not themselves create a response.
Servlet Filters are pluggable java components that we can use to intercept and process requests before they are sent to servlets and response after servlet code is finished and before container sends the response back to the client.
setContentType. Sets the content type of the response being sent to the client, if the response has not been committed yet. The given content type may include a character encoding specification, for example, text/html;charset=UTF-8 .
The codebase I am using, calls the getOutputStream method, instead of getWriter when it processes the response, so the examples included in the other answer doesn't help. Here is a more complete answer that works with both the OutputStream and the PrintWriter, even erroring correctly, if the writer is accessed twice. This is derived from the great example, DUMP REQUEST AND RESPONSE USING JAVAX.SERVLET.FILTER.
import javax.servlet.*; import javax.servlet.http.*; import java.io.*; public class MyFilter implements Filter { private FilterConfig filterConfig = null; private static class ByteArrayServletStream extends ServletOutputStream { ByteArrayOutputStream baos; ByteArrayServletStream(ByteArrayOutputStream baos) { this.baos = baos; } public void write(int param) throws IOException { baos.write(param); } } private static class ByteArrayPrintWriter { private ByteArrayOutputStream baos = new ByteArrayOutputStream(); private PrintWriter pw = new PrintWriter(baos); private ServletOutputStream sos = new ByteArrayServletStream(baos); public PrintWriter getWriter() { return pw; } public ServletOutputStream getStream() { return sos; } byte[] toByteArray() { return baos.toByteArray(); } } public class CharResponseWrapper extends HttpServletResponseWrapper { private ByteArrayPrintWriter output; private boolean usingWriter; public CharResponseWrapper(HttpServletResponse response) { super(response); usingWriter = false; output = new ByteArrayPrintWriter(); } public byte[] getByteArray() { return output.toByteArray(); } @Override public ServletOutputStream getOutputStream() throws IOException { // will error out, if in use if (usingWriter) { super.getOutputStream(); } usingWriter = true; return output.getStream(); } @Override public PrintWriter getWriter() throws IOException { // will error out, if in use if (usingWriter) { super.getWriter(); } usingWriter = true; return output.getWriter(); } public String toString() { return output.toString(); } } public void init(FilterConfig filterConfig) throws ServletException { this.filterConfig = filterConfig; } public void destroy() { filterConfig = null; } public void doFilter( ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { CharResponseWrapper wrappedResponse = new CharResponseWrapper( (HttpServletResponse)response); chain.doFilter(request, wrappedResponse); byte[] bytes = wrappedResponse.getByteArray(); if (wrappedResponse.getContentType().contains("text/html")) { String out = new String(bytes); // DO YOUR REPLACEMENTS HERE out = out.replace("</head>", "WTF</head>"); response.getOutputStream().write(out.getBytes()); } else { response.getOutputStream().write(bytes); } } }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With