• Bug
  • Status: Closed
  • 2 Major
  • Resolution: Fixed
  • ehcache-web
  • lorban
  • Reporter: lorban
  • March 25, 2010
  • 0
  • Watchers: 1
  • July 27, 2012
  • March 25, 2010

Description

GzipFilter fails when the headers are already sent and thus the HttpServletResponse was commited, you get this exception with Weblogic:

net.sf.ehcache.constructs.web.ResponseHeadersNotModifiableException: Failure when attempting to set Content-Encoding: gzip at net.sf.ehcache.constructs.web.ResponseUtil.addGzipHeader(ResponseUtil.java:128) at net.sf.ehcache.constructs.web.filter.GzipFilter.doFilter(GzipFilter.java:116) at net.sf.ehcache.constructs.web.filter.Filter.doFilter(Filter.java:86) at weblogic.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.java:42) …

This happens when nested code calls HttpServletResponse.flushBuffer().

see: http://forums.terracotta.org/forums/posts/list/3354.page

Comments

Ludovic Orban 2010-03-25

This bug also occurs with Jetty (and I suspect most other app servers too); Jetty just responds with garbage instead of throwing an exception like Weblogic does.

A new flag in GenericResponseWrapper has been implemented (disableFlushBuffer) so that when set, flushBuffer() calls aren’t forwarded anymore on the wrapped HttpServletResponse.

Arnauld Loyer 2010-04-01

We’d some issues related to this fix when the response is not effectively sent. Indeed in case of a redirect, for example, the headers are kept but never flushed.

GzipFilter.java

//return on error or redirect code, because response is already committed
int statusCode = wrapper.getStatus();
if (statusCode != HttpServletResponse.SC_OK) { +        ResponseUtil.setHeaders(response, wrapper.getHeaders());
      return;
}

Same thing afterward when writing the content :

   // Write the zipped body
   ResponseUtil.addGzipHeader(response); +     ResponseUtil.setHeaders(response, wrapper.getHeaders());
   response.setContentLength(compressedBytes.length);
   response.getOutputStream().write(compressedBytes);

ResponseUtil.java : method added

/** * Set the headers in the response object. * * @param headers headers to set in response * @param response */ public static void setHeaders(final Collection headers, final HttpServletResponse response) {

    final int header = 0;
    final int value = 1;

    for (Iterator iterator = headers.iterator(); iterator.hasNext();) {
        final String[] headerPair = (String[]) iterator.next();
        response.addHeader(headerPair[header], headerPair[value]);
    }
}

aside of this @see CachingFilter.java

/** * Set the headers in the response object, excluding the Gzip header * * @param pageInfo * @param requestAcceptsGzipEncoding * @param response */ protected void setHeaders(final PageInfo pageInfo, boolean requestAcceptsGzipEncoding, final HttpServletResponse response) {

    final Collection headers = pageInfo.getResponseHeaders(); +      ResponseUtil.setHeader(response, headers); -       final int header = 0; -       final int value = 1;
  • for (Iterator iterator = headers.iterator(); iterator.hasNext();) {
  • final String[] headerPair = (String[]) iterator.next();
  • response.addHeader(headerPair[header], headerPair[value]);
  • } }