How to make Jersey use GZip compression for the response message body

后端 未结 1 1244
旧时难觅i
旧时难觅i 2021-01-04 05:04

I am trying to write a simple Jersey application that sends files from a Jersey client to a Jersey server and back. However, the files only seem to be encoded on the way fro

相关标签:
1条回答
  • 2021-01-04 05:35

    I figured it out by looking through the Jersey library. For the server side, the following configuration is necessary:

    @Override
    @SuppressWarnings("unchecked")
    protected Application configure() {
        ResourceConfig resourceConfig = new ResourceConfig(MyResource.class);
        EncodingFilter.enableFor(resourceConfig, GZipEncoder.class);
        return resourceConfig;
    }
    

    Under the convers, EncodingFilter#enableFor(ResourceConfig.Class<? extends ContentEncoder>[])registers an EncodingFilter and the specified GZipEncoder with the given ResourceConfig.

    I guess the reason behind this detour in the registration lies in the fact that any encoding needs to happen in two stages. First, the EncodingFilter (which is an actual ContainerResponseFilter modifies the header of the response by setting Content-Encoding to gzip. At the same time, a filter cannot modify the entity stream of the message body since the filter is invoked before this stream is even created. Therefore, the stream modification must be processed by a WriterInterceptor which is triggered after the processing of the filter and also after the creation of the entity stream.

    For this reason, only registering the GZipEncoder will work for the request decoding when the Content-Encoding header is set to gzip by the client which occurs independently of the server's creation.

    The example I gave with my 'GZipWriterInterceptor' is basically a poorly implemented version of the EncodingFilter. Of course, the header should be set in a filter and not in an interceptor. It says in the documentation:

    Whereas filters are primarily intended to manipulate request and response parameters like HTTP headers, URIs and/or HTTP methods, interceptors are intended to manipulate entities, via manipulating entity input/output streams

    Therefore, gzip encoding cannot simply be activated by registering a GZipEncoder, it needs to be registered with a filter, as well. This is why I expected both to be bundled in a Feature.

    Important: There are two EncodingFilter classes within Jersey. One belongs to the client, the other belongs to the server implementation. Do not use the wrong one since they do fundamentally different things. Unfortunately, you will have both of them on your class path when running unit tests since they rely on the client interface.

    0 讨论(0)
提交回复
热议问题