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 from the client to the server but not the other way. I wonder how I can change this behavior.
I am testing this in a simple example:
public class GZipEncodingTest extends JerseyTest {
private static final String PATH = "/";
private static final String QUESTION = "foo", ANSWER = "bar";
private static final String ENCODING_GZIP = "gzip";
@Path(PATH)
public static class MyResource {
@POST
public Response handle(String question) throws IOException {
assertEquals(QUESTION, question);
return Response.ok(ANSWER).build(); // (1)
}
}
@Override
protected Application configure() {
enable(TestProperties.LOG_TRAFFIC);
enable(TestProperties.DUMP_ENTITY);
return new ResourceConfig(MyResource.class, GZipEncoder.class);
}
@Override
@SuppressWarnings("unchecked")
protected void configureClient(ClientConfig config) {
config.register(new EncodingFeature(ENCODING_GZIP, GZipEncoder.class));
}
@Test
public void testHeaders() throws Exception {
Response response = target().path(PATH).request().post(Entity.text(QUESTION));
assertEquals(ANSWER, response.readEntity(String.class));
}
}
From the logged dump, I can tell that the request is as intended: the content encoding is signaled in the header and applied on the request message body. The Accept-Encoding is also set. The server understands the applied gzip compression and unzips the request message body. However, it ignores the fact that the client accepts a gzipped response and sends the response message body uncompressed.
When I append encoding(ENCODING_GZIP)
in line (1) in the Response
-builder chain, I get the result I am looking for. However, I want to only apply the encoding if it was marked as acceptable in the request. Furthermore, I want to ally this feature application wide and not only for specific responses.
I can of course add such a feature manually with a WriterInterceptor
:
public class GZipWriterInterceptor implements WriterInterceptor {
@Override
public void aroundWriteTo(WriterInterceptorContext context)
throws IOException, WebApplicationException {
context.getHeaders().add(HttpHeaders.CONTENT_ENCODING, ENCODING_GZIP);
context.proceed();
}
}
but I am convinced that this is unnecessary boiler plate.
The EncodingFeature
seems to only be a part of the client library. I am basically looking for a possibility to make the Jersey server encode data as gzip whenever the request suggested the encoding via accept-encoding.
When I try to search for solutions on the web, I find plenty. Most of them concern Jersey 1. Some of them suggest adding a listener to the GrizzlyServer (which would be Jersey specific and not JAX-RS?). Then there are plenty classes within the Jersey 2 dependency tree that suggest GZip encoding:
org.glassfish.grizzly.http.GZipContentEncoding
org.glassfish.jersey.message.GZipEncoder
org.glassfish.grizzly.compression.zip.GZipEncoder
org.glassfish.grizzly.compression.zip.GZipDecoder
org.glassfish.grizzly.compression.zip.GZipFilter
I found that people on the web suggest using any of them even though I like to think that org.glassfish.jersey
seems to be the right choice since it is an actual Jersey dependency. Not to speak of those that are found in the ApacheConnector
related libraries. I have no idea which one I should actually use.