package com.netflix.eureka.cluster;
import javax.ws.rs.core.HttpHeaders;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;
import com.netflix.eureka.EurekaServerConfig;
import com.sun.jersey.api.client.AbstractClientRequestAdapter;
import com.sun.jersey.api.client.ClientHandlerException;
import com.sun.jersey.api.client.ClientRequest;
import com.sun.jersey.api.client.ClientRequestAdapter;
import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.filter.ClientFilter;
/**
* Eureka specific GZIP content filter handler.
*/
public class DynamicGZIPContentEncodingFilter extends ClientFilter {
private static final String GZIP_ENCODING = "gzip";
private final EurekaServerConfig config;
public DynamicGZIPContentEncodingFilter(EurekaServerConfig config) {
this.config = config;
}
@Override
public ClientResponse handle(ClientRequest request) {
// If 'Accept-Encoding' is not set, assume gzip as a default
if (!request.getHeaders().containsKey(HttpHeaders.ACCEPT_ENCODING)) {
request.getHeaders().add(HttpHeaders.ACCEPT_ENCODING, GZIP_ENCODING);
}
if (request.getEntity() != null) {
Object requestEncoding = request.getHeaders().getFirst(HttpHeaders.CONTENT_ENCODING);
if (GZIP_ENCODING.equals(requestEncoding)) {
request.setAdapter(new GzipAdapter(request.getAdapter()));
} else if (isCompressionEnabled()) {
request.getHeaders().add(HttpHeaders.CONTENT_ENCODING, GZIP_ENCODING);
request.setAdapter(new GzipAdapter(request.getAdapter()));
}
}
ClientResponse response = getNext().handle(request);
String responseEncoding = response.getHeaders().getFirst(HttpHeaders.CONTENT_ENCODING);
if (response.hasEntity() && GZIP_ENCODING.equals(responseEncoding)) {
response.getHeaders().remove(HttpHeaders.CONTENT_ENCODING);
decompressResponse(response);
}
return response;
}
private boolean isCompressionEnabled() {
return config.shouldEnableReplicatedRequestCompression();
}
private static void decompressResponse(ClientResponse response) {
InputStream entityInputStream = response.getEntityInputStream();
GZIPInputStream uncompressedIS;
try {
uncompressedIS = new GZIPInputStream(entityInputStream);
} catch (IOException ex) {
try {
entityInputStream.close();
} catch (IOException ignored) {
}
throw new ClientHandlerException(ex);
}
response.setEntityInputStream(uncompressedIS);
}
private static final class GzipAdapter extends AbstractClientRequestAdapter {
GzipAdapter(ClientRequestAdapter cra) {
super(cra);
}
@Override
public OutputStream adapt(ClientRequest request, OutputStream out) throws IOException {
return new GZIPOutputStream(getAdapter().adapt(request, out));
}
}
}