GZip Filter

Buried in a .war file available here, there’s a neat utility that helps provide a little bit of performance improvement for web applications. There are three files:

  1. GZIPFilter
  2. GZIPResponseWrapper
  3. GZIPResponseStream

Drop these classes into your web app, and configure them in your web.xml file, like so:

<filter>
  <filter-name>com.jspbook.GZIPFilter</filter-name>
  <filter-class>com.jspbook.GZIPFilter</filter-class>
</filter>

...

<filter-mapping>
  <filter-name>com.jspbook.GZIPFilter</filter-name>
  <url-pattern>/*</url-pattern>
</filter-mapping>

The filter will intercept all requests, and look to see if the browser supports GZIP encoding. Usually this is done with an “Accept-Encoding” header, and all the major browsers support GZIP encoding.

There’s one glitch I’ve found. IE doesn’t like it when you GZIP a zip file. What appears to happen is that IE doesn’t try to unencode a GZIP file, but rather sends it directly to the .zip application. In my case, the WinZip tried to open the file, and complained because there’s some extra GZIP header information on the file. What it ends up with is a corrupt file.

So I made some changes to GZIPResponseWrapper, as follows:

public void setContentLength(int length) {
  if (this.alreadyCompressed) {
    this.origResponse.setContentLength(length);
  }
  this.contentLength = length;
}

public void setContentType(String s) {
  if (s != null && s.toLowerCase().startsWith(
      "application/x-zip-compressed")) {
     this.alreadyCompressed = true;
     if (this.contentLength != null) {
       this.origResponse.setContentLength(this.contentLength);
     }
  }
  this.origResponse.setContentType(s);
}

public ServletOutputStream getOutputStream() throws IOException {
  ...

  if (stream == null && this.alreadyCompressed) {
    stream = this.origResponse.getOutputStream();
  } else if (stream == null) {
    stream = createOutputStream();
  }
  return (stream);
}

If a later calling servlet tries to set a compressed file content header, then the wrapper skips the GZIP encoding.

The check isn’t perfect: if a Servlet starts changing its mind about the content type, I might end up skipping compression where it would still help.

Another revision that might be useful if you’re using Spring in your code is to have the GZIPFilter extend the OncePerRequestFilter, so that the wrappers don’t end up getting nested (which can happen if there’s request dispatching in your code).

It's only fair to share...
Share on FacebookGoogle+Tweet about this on TwitterShare on LinkedIn

Leave a Reply