Jetty responds with 400 Bad Request when request C

2019-05-30 12:59发布

问题:

Spring MVC Java 1.8.0_45-b14 backend running on Jetty 9.3.0.v20150612 is working well with uncompressed requests, but fails to accept compressed ones.

I've followed Gzip Handler configuration instructions here, made sure these are supported for POST requests as well. Though it doesn't say this configuration is at all for requests... it may be only for responses.

etc/jetty-gzip.xml -

<Configure id="Server" class="org.eclipse.jetty.server.Server">
  <Get id="next" name="handler" />
  <Set name="handler">
    <New id="GzipHandler" class="org.eclipse.jetty.server.handler.gzip.GzipHandler">
      <Set name="handler"><Ref refid="next" /></Set>
      <Set name="minGzipSize"><Property name="jetty.gzip.minGzipSize" deprecated="gzip.minGzipSize" default="2048"/></Set>
      <Set name="checkGzExists"><Property name="jetty.gzip.checkGzExists" deprecated="gzip.checkGzExists" default="false"/></Set>
      <Set name="compressionLevel"><Property name="jetty.gzip.compressionLevel" deprecated="gzip.compressionLevel" default="-1"/></Set>
      <Set name="excludedAgentPatterns">
        <Array type="String">
          <Item><Property name="jetty.gzip.excludedUserAgent" deprecated="gzip.excludedUserAgent" default=".*MSIE.6\.0.*"/></Item>
        </Array>
      </Set>

      <Set name="includedMethods">
        <Array type="String">
            <Item>GET</Item>
            <Item>POST</Item>
        </Array>
      </Set>

      <Set name="includedPaths">
        <Array type="String">
          <Item>/*</Item>
        </Array>
      </Set>

    </New>
  </Set>
</Configure>

In web.xml -

<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,image/svg+xml,application/json</param-value>
    </init-param>
    <init-param>
        <param-name>minGzipSize</param-name>
        <param-value>500</param-value>
    </init-param>
</filter>
<filter-mapping>
    <filter-name>GzipFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

This happens with an Android client and also reproduces with HTTP Client app (Paw), here's a request example -

POST /report?v=1 HTTP/1.1
Content-Encoding: gzip
Content-Type: application/json
Host: 10.0.0.1:8080
Connection: close
User-Agent: Paw/2.2.2 (Macintosh; OS X/10.10.4) GCDHTTPRequest
Content-Length: 5845

xí\MÇuÝûWÔE(É`_¦(<EtD&)%:¦OTè.EôÔU53¬¼ð"ÇYfÆ'®ì­/áÿʽ¯ª
r(ʲä#èúz÷Ý÷^5èýR;Úå;ÕÎÿöºÊuW«ß«v«ß¿ø³:VÕ)Õ .. BINARY ...

Response -

HTTP/1.1 400 Bad Request
Content-Type: text/html;charset=iso-8859-1
Cache-Control: must-revalidate,no-cache,no-store
Content-Length: 242
Connection: close

Does Jetty even support compressed requests? (couldn't find a clear evidence for that)

What's wrong with my config?

回答1:

First, Remove GzipFilter from your web.xml it's not relevant anymore (starting with Jetty 9.3.0)

GzipHandler is the new replacement for all old filter based gzip filters (GzipFilter, AsyncGzipFilter, and IncludableGzipFilter).

It's been designed to function at a level more fundamental to the connection streams, something that the filter based approaches could not do in the world of Async I/O.

That being said ... GzipHandler in Jetty 9.3.0 only has an implementation designed for the Response body content. (Just like the GzipFilters of before)

What we learned however, is that some projects extended our GzipFilter to add Request content body gzip handling as well. Which our change from GzipFilter to GzipHandler broke.

We have an open bug about that at https://bugs.eclipse.org/471577 (DropWizard extended GzipFilter for their own BiDiGzipFilter)

We recognize that there could be some useful functions for Gzip on the request content body, but we don't have an implementation for that yet. (hint, hint, drop a patch on us)