Created
August 26, 2013 19:55
-
-
Save davidmc24/6345889 to your computer and use it in GitHub Desktop.
Example Feign client with support for GZIP encoding of request bodies
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package sample; | |
import dagger.Lazy; | |
import dagger.Module; | |
import dagger.Provides; | |
import feign.Client; | |
import feign.Request; | |
import feign.Request.Options; | |
import feign.Response; | |
import javax.inject.Inject; | |
import javax.net.ssl.HostnameVerifier; | |
import javax.net.ssl.HttpsURLConnection; | |
import javax.net.ssl.SSLSocketFactory; | |
import java.io.IOException; | |
import java.io.InputStream; | |
import java.io.InputStreamReader; | |
import java.io.OutputStream; | |
import java.io.Reader; | |
import java.net.HttpURLConnection; | |
import java.net.URL; | |
import java.util.Collection; | |
import java.util.LinkedHashMap; | |
import java.util.List; | |
import java.util.Map; | |
import java.util.zip.GZIPOutputStream; | |
import static feign.Util.CONTENT_LENGTH; | |
import static feign.Util.UTF_8; | |
@Module(library = true, overrides = true, complete = false) | |
public class MyClientModule { | |
static final String CONTENT_ENCODING = "Content-Encoding"; | |
static final String GZIP_ENCODING = "gzip"; | |
@Provides | |
Client httpClient(MyClient client) { | |
return client; | |
} | |
/** | |
* This is heavily based on the default client. It adds GZip encoded bodies. | |
*/ | |
public static class MyClient implements Client { | |
private final Lazy<SSLSocketFactory> sslContextFactory; | |
private final Lazy<HostnameVerifier> hostnameVerifier; | |
@Inject | |
public MyClient(Lazy<SSLSocketFactory> sslContextFactory, Lazy<HostnameVerifier> hostnameVerifier) { | |
this.sslContextFactory = sslContextFactory; | |
this.hostnameVerifier = hostnameVerifier; | |
} | |
@Override public Response execute(Request request, Options options) throws IOException { | |
HttpURLConnection connection = convertAndSend(request, options); | |
return convertResponse(connection); | |
} | |
HttpURLConnection convertAndSend(Request request, Options options) throws IOException { | |
final HttpURLConnection connection = (HttpURLConnection) new URL(request.url()).openConnection(); | |
if (connection instanceof HttpsURLConnection) { | |
HttpsURLConnection sslCon = (HttpsURLConnection) connection; | |
sslCon.setSSLSocketFactory(sslContextFactory.get()); | |
sslCon.setHostnameVerifier(hostnameVerifier.get()); | |
} | |
connection.setConnectTimeout(options.connectTimeoutMillis()); | |
connection.setReadTimeout(options.readTimeoutMillis()); | |
connection.setAllowUserInteraction(false); | |
connection.setInstanceFollowRedirects(true); | |
connection.setRequestMethod(request.method()); | |
boolean gzipEncodedRequest = | |
request.headers().containsKey(CONTENT_ENCODING) && | |
request.headers().get(CONTENT_ENCODING).contains(GZIP_ENCODING); | |
Integer contentLength = null; | |
for (String field : request.headers().keySet()) { | |
for (String value : request.headers().get(field)) { | |
if (field.equals(CONTENT_LENGTH)) { | |
if (!gzipEncodedRequest) { | |
contentLength = Integer.valueOf(value); | |
connection.addRequestProperty(field, value); | |
} | |
} else { | |
connection.addRequestProperty(field, value); | |
} | |
} | |
} | |
if (request.body() != null) { | |
if (contentLength != null) { | |
connection.setFixedLengthStreamingMode(contentLength); | |
} else { | |
connection.setChunkedStreamingMode(8196); | |
} | |
connection.setDoOutput(true); | |
OutputStream out = connection.getOutputStream(); | |
try { | |
if (gzipEncodedRequest) { | |
out = new GZIPOutputStream(out); | |
} | |
out.write(request.body().getBytes(UTF_8)); | |
} finally { | |
try { | |
out.close(); | |
} catch (IOException suppressed) { // NOPMD | |
} | |
} | |
} | |
return connection; | |
} | |
Response convertResponse(HttpURLConnection connection) throws IOException { | |
int status = connection.getResponseCode(); | |
String reason = connection.getResponseMessage(); | |
Map<String, Collection<String>> headers = new LinkedHashMap<String, Collection<String>>(); | |
for (Map.Entry<String, List<String>> field : connection.getHeaderFields().entrySet()) { | |
// response message | |
if (field.getKey() != null) | |
headers.put(field.getKey(), field.getValue()); | |
} | |
Integer length = connection.getContentLength(); | |
if (length == -1) | |
length = null; | |
InputStream stream; | |
if (status >= 400) { | |
stream = connection.getErrorStream(); | |
} else { | |
stream = connection.getInputStream(); | |
} | |
Reader body = stream != null ? new InputStreamReader(stream) : null; | |
return Response.create(status, reason, headers, body, length); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment