简体   繁体   English

Jetty-servlets GzipFilter不适用于Jetty 9.2.7.v20150116和Spring

[英]Jetty-servlets GzipFilter doesn't work with Jetty 9.2.7.v20150116 and Spring

I'm using following xml in my web.xml -file to configure the GzipFilter to my Spring application which I'm running with Jetty. 我在web.xml -file中使用以下xml将GzipFilter配置为与Jetty一起运行的Spring应用程序。 I would expect to see the resource size getting smaller when inspecting with developer tools in Chrome and also I would expect to see the "encoding" to have value "gzip" in response headers. 在Chrome中使用开发人员工具进行检查时,我希望资源的大小会变小,并且响应头中的“编码”值也应该为“ gzip”。 However, none of these are visible. 但是,这些都不是可见的。

However when examining with debugging tools in my IDE I noticed that the filter gets applied (I put the break point to GzipFilter) and also I noticed that the etag-headers have an -gzip extension in responses, when examining with developer tools. 但是,当在我的IDE中使用调试工具进行检查时,我注意到过滤器已应用(我将断点放置在GzipFilter上),并且在使用开发人员工具进行检查时,我还注意到etag-header在响应中具有-gzip扩展名。 However the contents don't seem to be zipped. 但是,内容似乎没有压缩。

I'm running out of ideas and would appreciate any help. 我的想法不多了,不胜感激。

<filter>
  <filter-name>GzipFilter</filter-name>
  <filter-class>org.eclipse.jetty.servlets.GzipFilter</filter-class>
  <init-param>
     <param-name>mimeTypes</param-name>
     <param-value>text/html,text/plain,text/xml,application/xhtml+xml,text/css,application/javascript,application/json,image/svg+xml</param-value>
  </init-param>
</filter>
<filter-mapping>
  <filter-name>GzipFilter</filter-name>
  <url-pattern>/*</url-pattern>
</filter-mapping>

Edit: Adding request and response headers 编辑:添加请求和响应头

 Request:
 GET ******* HTTP/1.1
 Host: localhost:8081
 Connection: keep-alive
 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6)       AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36
 Accept: */*
 Referer: http://localhost:8081/
 Accept-Encoding: gzip, deflate, sdch
 Accept-Language: en-US,en;q=0.8,fi;q=0.6
 Cookie: XSRF-TOKEN=******; JSESSIONID=*******

 Response:
 HTTP/1.1 200 OK
 Date: Mon, 29 Aug 2016 13:59:59 GMT
 Cache-Control: public
 Date: Mon, 29 Aug 2016 13:59:59 GMT
 Content-Type: application/javascript;charset=UTF-8
 Vary: Accept-Encoding, User-Agent
 ETag: "0f93db3b42f19c57f4a216dd80f63bae5--gzip"
 Server: Jetty(9.2.7.v20150116)
 Transfer-Encoding: chunked

The --gzip suffix on the ETag is used by the GzipFilter to know if the request processing actually went through a GzipFilter . ETag上的--gzip后缀由GzipFilter使用,以了解请求处理是否实际上通过GzipFilter

It's purpose is to break the ETag support in DefaultServlet if the request was once gzipped, and is now no longer gzipped. 目的是如果请求曾经被压缩,现在不再被压缩,则将破坏DefaultServletETag支持。

Meaning this flow: 含义如下:

  • Server configured with gzip 使用gzip配置的服务器
  • Request to resource /foo.js 请求资源/foo.js
  • DefaultServlet sends response to /foo.js with ETag: abcdef DefaultServlet使用ETag: abcdef将响应发送到/foo.js
  • GzipFilter is configured to compressed application/javascript , so it compressed the response and alters the ETag to ETag: abcdef--gzip GzipFilter配置为压缩application/javascript ,因此它压缩了响应并将ETag更改为ETag: abcdef--gzip
  • Some time later, the GzipFilter is reconfigured (different url-pattern, different mime-types, whatever) 一段时间后,重新配置了GzipFilter(不同的url模式,不同的mime类型,等等)
  • Same User-Agent requests resource /foo.js with ETag: abcdef--gzip , but this doesn't go through GzipFilter anymore, so the DefaultServlet will not recognize the ETag and serve the content afresh. 相同的User-Agent请求带有ETag: abcdef--gzip资源/foo.js ,但这不再通过GzipFilter进行,因此DefaultServlet将无法识别ETag并重新提供内容。

As for why your content isn't being compressed, its either due to the way you are setting the response.setContentType() or the size of the response body content. 至于为什么不压缩您的内容,可能是由于您设置response.setContentType()还是响应主体内容的大小所致。

First, you'll need to make sure that you always set response status codes, response headers, and (optionally) response buffer sizes before you access the response outputstream (or writer), as the .getOutputStream() and .getWriter() both use the values from the response object to set themselves up. 首先,您需要确保访问响应输出流(或编写器) 之前始终设置响应状态代码,响应标头和(可选)响应缓冲区大小,因为.getOutputStream().getWriter()都使用响应对象中的值进行设置。

The GzipFilter also uses these values to know if the response should be compressed or not. GzipFilter还使用这些值来知道是否应压缩响应。

Next, the size of the response body content is important, as there is a lower limit to the the response size before the GzipFilter will get involved. 接下来,响应主体内容的大小很重要,因为在涉及GzipFilter之前,响应大小有一个下限。 (its actually inefficient to compress most content below the GzipFilter.minGzipSize ) (它实际上无法有效地压缩GzipFilter.minGzipSize以下的大多数内容)

In your version of Jetty, I believe the minGzipSize is 256 bytes. 在您的Jetty版本中,我相信minGzipSize是256个字节。

As your pasted response headers is without a Content-Length and Transfer-Encoding: chunked , I cannot tell how big your response actually was. 由于您粘贴的响应标头没有Content-LengthTransfer-Encoding: chunked ,因此我无法确定您的响应实际有多大。

Important upgrade note: GzipFilter in Jetty 9.3+ has been completely deprecated and results in a no-op if used. 重要的升级说明:Jetty 9.3+中的GzipFilter已被完全弃用,如果使用,将导致无操作。 This is because the filter approach for Gzip compression is highly problematic when Servlet 3.1 and Async I/O are in use. 这是因为在使用Servlet 3.1和异步I / O时,用于Gzip压缩的过滤器方法存在很大问题。

The Gzip support in Jetty 9.3+ has been moved outside of the Servlet spec and into a low level HttpOutput.Interceptor pattern that only compresses the content after a flush has occurred (either automatic internal or application specified). Jetty 9.3+中的Gzip支持已移出Servlet规范,并移至较低级别的HttpOutput.Interceptor模式,该模式仅在发生刷新(指定内部自动或应用程序)后才压缩内容。

To say this another way, the servlet buffers are not compressed as they are written from the application to the servlet buffers like in Jetty 9.2 and before. 换句话说,servlet缓冲区在从应用程序写入servlet缓冲区时不会被压缩,就像在Jetty 9.2及之前的版本中一样。 They are instead only compressed when they leave the servlet buffers and enter the network level writes. 相反,仅当它们离开servlet缓冲区并进入网络级写入时才压缩它们。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM