How do I minify dynamic HTML responses in Spring?
I managed to do this by adding a javax.servlet.Filter
component that is using com.googlecode.htmlcompressor
into Spring
First the Filter
;
@Componentpublic class HtmlFilter implements Filter { protected FilterConfig config; public void init(FilterConfig config) throws ServletException { this.config = config; } public void destroy() { } public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException { ServletResponse newResponse = response; if (request instanceof HttpServletRequest) { newResponse = new CharResponseWrapper((HttpServletResponse) response); } chain.doFilter(request, newResponse); if (newResponse instanceof CharResponseWrapper) { String text = newResponse.toString(); if (text != null) { HtmlCompressor htmlCompressor = new HtmlCompressor(); response.getWriter().write(htmlCompressor.compress(text)); } } }}
and relevant CharResponseWrapper
;
class CharResponseWrapper extends HttpServletResponseWrapper { protected CharArrayWriter charWriter; protected PrintWriter writer; protected boolean getOutputStreamCalled; protected boolean getWriterCalled; public CharResponseWrapper(HttpServletResponse response) { super(response); charWriter = new CharArrayWriter(); } public ServletOutputStream getOutputStream() throws IOException { if (getWriterCalled) { throw new IllegalStateException("getWriter already called"); } getOutputStreamCalled = true; return super.getOutputStream(); } public PrintWriter getWriter() throws IOException { if (writer != null) { return writer; } if (getOutputStreamCalled) { throw new IllegalStateException("getOutputStream already called"); } getWriterCalled = true; writer = new PrintWriter(charWriter); return writer; } public String toString() { String s = null; if (writer != null) { s = charWriter.toString(); } return s; }}
Works fantastically. Converts an html this ugly;
<!DOCTYPE HTML><html><head> <title> A Simple <!-- Test--> HTML Document <!-- Test--> </title></head><body> <p>This is a very simple HTML document</p> <!-- Test--><p>It only has two<!-- Test--> paragraphs</p> <!-- Test--></body></html>
into this;
<!DOCTYPE HTML> <html> <head> <title> A Simple HTML Document </title> </head> <body> <p>This is a very simple HTML document</p> <p>It only has two paragraphs</p> </body> </html>