Jetty 8 GzipFilter does not apply sometimes
I just updated my web server from Jetty 6.x to Jetty 8.0.1, and for some reason, when I do the exact same request, sometimes the response has been Gzipped and sometimes not.
Here is what the request and response look like at the beginning of the service() method of the servlet:
Request: [GET /test/hello_world?param=test]@11538114 org.eclipse.jetty.server.Request@b开发者_StackOverflow社区00ec2
Response: org.eclipse.jetty.servlets.GzipFilter$2@1220fd1
WORKED!
Request:[GET /test/hello_world?param=test]@19386718 org.eclipse.jetty.server.Request@127d15e
Response:HTTP/1.1 200
Connection: close
FAILED!
Here is my GzipFilter declaration:
EnumSet<DispatcherType> all = EnumSet.of(DispatcherType.ASYNC, DispatcherType.ERROR, DispatcherType.FORWARD,
DispatcherType.INCLUDE, DispatcherType.REQUEST);
FilterHolder gzipFilter = new FilterHolder(new GzipFilter());
gzipFilter.setInitParameter("mimeTypes", "text/javascript");
gzipFilter.setInitParameter("minGzipSize", "0");
context.addFilter(gzipFilter, "/test/*", all);
The Javadoc says that:
GZIP Filter This filter will gzip the content of a response if:
The filter is mapped to a matching path ==>
The response status code is >=200 and <300
The content length is unknown or more than the minGzipSize initParameter or the minGzipSize is 0(default)
The content-type is in the comma separated list of mimeTypes set in the mimeTypes initParameter or if no mimeTypes are defined the content-type is not "application/gzip"
No content-encoding is specified by the resource
It looks to me that all those conditions are met in my case, except maybe the last one "No content-encoding is specified by the resource". How can I verify that?
Plus, for a reason I ignore too, when the response is not filtered with GzipFilter, response.getWriter() throws an IO Exception. Why is that?
I had the same problem, and found 2 causes:
- If any of your servlets prematurely calls response.getWriter().flush(), the GZipFilter won't work. In my case both Freemarker in Spring MVC and Sitemesh were doing that, so I had to set the Freemarker setting "auto_flush" to "false" for both the Freemarker servlet and the Spring MVC Freemarker config object.
- If you use the ordinary GzipFilter, for some reason it doesn't let you set any headers in the "including" stage on Jetty. So I had to use IncludableGzipFilter instead.
After I made these changes, it works for me. Hope that helps you as well.
May I suggest you to use Fiddler to track you HTTP requests?
Maybe, a header like Last-Modified
indicates to your browser that the content of your request /test/hello_world?param=test
is still the same... So your browser reuses what is in its cache and simply close the request, without reading its content...
What happens with two different requests?
/test/hello_world?param=test
/test/hello_world?param=test&foo=1
You can use another GzipFilter. Add it to your maven or download the jar file http://mvnrepository.com/artifact/net.sourceforge.pjl-comp-filter/pjl-comp-filter/1.7
And then just change a bit your code:
EnumSet<DispatcherType> all = EnumSet.of(DispatcherType.ASYNC, DispatcherType.ERROR, DispatcherType.FORWARD, DispatcherType.INCLUDE, DispatcherType.REQUEST);
FilterHolder gzipFilter = new FilterHolder(new CompressingFilter());
gzipFilter.setInitParameter("includeContentTypes", "text/javascript");
context.addFilter(gzipFilter, "/test/*", all);
I've had the same issue and this fixed the problem.
精彩评论