EHC ❯ GzipFilter failure when attempting to set Content-Encoding: gzip
-
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
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]);
- } }
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.