Skip to content

Commit

Permalink
GH-934: Update Default Client to wrap GZIP Responses correctly
Browse files Browse the repository at this point in the history
This change updates the Input Stream handling when using the Default
client implementation to detect when a response is `gzipped` and
wrap it in a `GZipInputStream`.

This addresses any issues related to compression when using the
default client.
  • Loading branch information
kdavisk6 committed Dec 29, 2020
1 parent f8ad867 commit 0a048b1
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 1 deletion.
15 changes: 14 additions & 1 deletion core/src/main/java/feign/Client.java
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
import java.util.List;
import java.util.Map;
import java.util.zip.DeflaterOutputStream;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
Expand Down Expand Up @@ -129,7 +130,11 @@ Response convertResponse(HttpURLConnection connection, Request request) throws I
if (status >= 400) {
stream = connection.getErrorStream();
} else {
stream = connection.getInputStream();
if (this.isGzip(connection)) {
stream = new GZIPInputStream(connection.getInputStream());
} else {
stream = connection.getInputStream();
}
}
return Response.builder()
.status(status)
Expand Down Expand Up @@ -216,6 +221,14 @@ HttpURLConnection convertAndSend(Request request, Options options) throws IOExce
}
return connection;
}

private boolean isGzip(HttpURLConnection connection) {
String contentEncoding = connection.getHeaderField("Content-Encoding");
if (Util.isNotBlank(contentEncoding)) {
return contentEncoding.equalsIgnoreCase("gzip");
}
return false;
}
}

/**
Expand Down
34 changes: 34 additions & 0 deletions core/src/test/java/feign/client/DefaultClientTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
import static org.assertj.core.api.Assertions.assertThat;
import static org.hamcrest.core.Is.isA;
import static org.junit.Assert.assertEquals;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.InetSocketAddress;
Expand All @@ -24,8 +26,11 @@
import java.net.Proxy.Type;
import java.net.SocketAddress;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.zip.GZIPOutputStream;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLSession;
import okio.Buffer;
import org.junit.Test;
import feign.Client;
import feign.Client.Proxied;
Expand Down Expand Up @@ -144,4 +149,33 @@ public void canCreateWithExplicitCredentials() throws Exception {
assertThat(connection).isNotNull().isInstanceOf(HttpURLConnection.class);
}


@Test
public void canSupportGzip() throws Exception {
/* enqueue a zipped response */
final String responseData = "Compressed Data";
server.enqueue(new MockResponse()
.addHeader("Content-Encoding", "gzip")
.setBody(new Buffer().write(compress(responseData))));

TestInterface api = newBuilder()
.target(TestInterface.class, "http://localhost:" + server.getPort());

String result = api.get();

/* verify that the response is unzipped */
assertThat(result).isNotNull()
.isEqualToIgnoringCase(responseData);

}

private byte[] compress(String data) throws Exception {
try (ByteArrayOutputStream bos = new ByteArrayOutputStream(data.length())) {
GZIPOutputStream gzipOutputStream = new GZIPOutputStream(bos);
gzipOutputStream.write(data.getBytes(StandardCharsets.UTF_8), 0, data.length());
gzipOutputStream.close();
return bos.toByteArray();
}

}
}

0 comments on commit 0a048b1

Please sign in to comment.