Skip to content

Instantly share code, notes, and snippets.

@leifoolsen
Last active July 19, 2023 20:19
Show Gist options
  • Save leifoolsen/2daf9749a3d89e9cab97 to your computer and use it in GitHub Desktop.
Save leifoolsen/2daf9749a3d89e9cab97 to your computer and use it in GitHub Desktop.
JAX-RS 2: How to compress response if client accepts gzip; "Accept-Encoding: gzip, deflate, sdch"
// Create a WriterInterceptor,
// see: https://jersey.java.net/documentation/latest/user-guide.html#d0e9728
import ...
@Provider
public class GZIPWriterInterceptor implements WriterInterceptor {
private final Logger logger = LoggerFactory.getLogger(getClass());
private HttpHeaders httpHeaders;
public GZIPWriterInterceptor(@Context @NotNull HttpHeaders httpHeaders) {
this.httpHeaders = httpHeaders;
}
@Override
public void aroundWriteTo(WriterInterceptorContext context)
throws IOException, WebApplicationException {
MultivaluedMap<String,String> requestHeaders = httpHeaders.getRequestHeaders();
List<String> acceptEncoding = MoreObjects.firstNonNull(
requestHeaders.get(HttpHeaders.ACCEPT_ENCODING), new ArrayList<String>());
// Compress if client accepts gzip encoding
for (String s : acceptEncoding) {
if(s.contains("gzip")) {
logger.debug("GZIP'ing response");
MultivaluedMap<String, Object> headers = context.getHeaders();
headers.add(HttpHeaders.CONTENT_ENCODING, "gzip");
//com.google.common.net.MediaType.GZIP);
final OutputStream outputStream = context.getOutputStream();
context.setOutputStream(new GZIPOutputStream(outputStream));
break;
}
}
context.proceed();
}
}
// If we're using the client api, then we need a ReaderInterceptor as well
import ...
public class GZIPReaderInterceptor implements ReaderInterceptor {
private final Logger logger = LoggerFactory.getLogger(getClass());
@Override
public Object aroundReadFrom(ReaderInterceptorContext context)
throws IOException, WebApplicationException {
MultivaluedMap<String,String> headers = context.getHeaders();
List<String> contentEncoding = MoreObjects.firstNonNull(
headers.get(HttpHeaders.CONTENT_ENCODING), new ArrayList<String>());
for (String s : contentEncoding) {
if(s.contains("gzip")) {
logger.debug("Decompressing GZIP");
final InputStream originalInputStream = context.getInputStream();
context.setInputStream(new GZIPInputStream(originalInputStream));
break;
}
}
return context.proceed();
}
}
// Register ReaderInterceptor on client-api
@BeforeClass
public static void startServer() throws Exception {
// Start the server
// ... Code ommited for brewety
// Create the client
Client c = ClientBuilder.newClient();
// Client interceptor to deflate GZIP'ed content on client side
c.register(GZIPReaderInterceptor.class);
target = c.target(server.getURI()).path(JerseyJpaApp.APPLICATION_PATH);
}
// Set header(HttpHeaders.ACCEPT_ENCODING, "gzip") in request
@Test
public void getBookByIsbnShouldReturn_OK() {
final Response response = target
.path(BookResource.RESOURCE_PATH)
.path(ISBN_TRAVELING_TO_INFINITY)
.request(MediaType.APPLICATION_JSON_TYPE)
.header(HttpHeaders.ACCEPT_ENCODING, "gzip")
.get();
assertEquals(Response.Status.OK.getStatusCode(), response.getStatus());
List<Object> objects = response.getHeaders().get("Content-Encoding");
assertNotNull(objects);
assertThat(objects.toString(), containsString("gzip"));
}
// That's it :-)
// If you're sending request from a browser then
// set "Accept-Encoding: gzip, deflate, sdch" before sending request
// Note: this is the default setting in Chrome (I think)
@leifoolsen
Copy link
Author

Basically same code as found here: https://jersey.java.net/documentation/latest/user-guide.html#d0e9728. We can extend further and combine HttpHeaders.CONTENT_ENCODING with the @compress annotation to compress only when request method is annotated with @compress. In this way we can return compressed content given that the client accepts gzip and response method is annotated with @compress

@PeterLaman
Copy link

After the call to proceed(), the GZIP stream must be explicitly closed (at least in Java-SE 1.8), or there will be no output.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment