Skip to content

Instantly share code, notes, and snippets.

@dodgex
Last active December 20, 2015 01:19
Show Gist options
  • Select an option

  • Save dodgex/6048213 to your computer and use it in GitHub Desktop.

Select an option

Save dodgex/6048213 to your computer and use it in GitHub Desktop.

Revisions

  1. dodgex revised this gist Sep 7, 2013. 1 changed file with 2 additions and 0 deletions.
    2 changes: 2 additions & 0 deletions OkHttpClientRequest.java
    Original file line number Diff line number Diff line change
    @@ -29,6 +29,8 @@ public OkHttpClientRequest(HttpURLConnection connection) {
    @Override
    public OutputStream getBody() throws IOException {
    if (this.body == null) {
    writeHeaders(headers);
    this.connection.connect();
    this.body = this.connection.getOutputStream();
    }
    if (shouldCompress()) {
  2. dodgex created this gist Jul 21, 2013.
    102 changes: 102 additions & 0 deletions OkHttpClientRequest.java
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,102 @@
    import java.io.IOException;
    import java.io.OutputStream;
    import java.net.HttpURLConnection;
    import java.net.URI;
    import java.net.URISyntaxException;
    import java.util.List;
    import java.util.Map;
    import java.util.zip.GZIPOutputStream;

    import org.springframework.http.ContentCodingType;
    import org.springframework.http.HttpHeaders;
    import org.springframework.http.HttpMethod;
    import org.springframework.http.client.ClientHttpRequest;
    import org.springframework.http.client.ClientHttpResponse;

    final class OkHttpClientRequest implements ClientHttpRequest {
    private final HttpURLConnection connection;
    private final HttpHeaders headers = new HttpHeaders();

    private boolean executed = false;

    private GZIPOutputStream compressedBody;
    private OutputStream body;

    public OkHttpClientRequest(HttpURLConnection connection) {
    this.connection = connection;
    }

    @Override
    public OutputStream getBody() throws IOException {
    if (this.body == null) {
    this.body = this.connection.getOutputStream();
    }
    if (shouldCompress()) {
    return getCompressedBody(this.body);
    } else {
    return this.body;
    }
    }

    @Override
    public HttpHeaders getHeaders() {
    return (this.executed ? HttpHeaders.readOnlyHttpHeaders(this.headers) : this.headers);
    }

    @Override
    public URI getURI() {
    try {
    return this.connection.getURL().toURI();
    } catch (URISyntaxException ex) {
    throw new IllegalStateException("Could not get HttpURLConnection URI: " + ex.getMessage(), ex);
    }
    }

    @Override
    public HttpMethod getMethod() {
    return HttpMethod.valueOf(this.connection.getRequestMethod());
    }

    @Override
    public ClientHttpResponse execute() throws IOException {
    try {
    if (this.body != null) {
    this.body.close();
    } else {
    writeHeaders(headers);
    this.connection.connect();
    }
    } catch (IOException ex) {
    // ignore
    }

    this.executed = true;
    return new OkHttpClientResponse(connection);
    }

    private boolean shouldCompress() {
    List<ContentCodingType> contentCodingTypes = this.headers.getContentEncoding();
    for (ContentCodingType contentCodingType : contentCodingTypes) {
    if (contentCodingType.equals(ContentCodingType.GZIP)) {
    return true;
    }
    }
    return false;
    }

    private OutputStream getCompressedBody(OutputStream body) throws IOException {
    if (this.compressedBody == null) {
    this.compressedBody = new GZIPOutputStream(body);
    }
    return this.compressedBody;
    }

    private void writeHeaders(HttpHeaders headers) {
    for (Map.Entry<String, List<String>> entry : headers.entrySet()) {
    String headerName = entry.getKey();
    for (String headerValue : entry.getValue()) {
    this.connection.addRequestProperty(headerName, headerValue);
    }
    }
    }
    }
    119 changes: 119 additions & 0 deletions OkHttpClientResponse.java
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,119 @@
    import java.io.IOException;
    import java.io.InputStream;
    import java.net.HttpURLConnection;
    import java.util.List;
    import java.util.zip.GZIPInputStream;

    import org.springframework.http.ContentCodingType;
    import org.springframework.http.HttpHeaders;
    import org.springframework.http.HttpStatus;
    import org.springframework.http.client.ClientHttpResponse;
    import org.springframework.util.StringUtils;

    final class OkHttpClientResponse implements ClientHttpResponse {
    private final HttpURLConnection connection;
    private static final String AUTH_ERROR = "Received authentication challenge is null";
    private static final String AUTH_ERROR_JELLY_BEAN = "No authentication challenges found";
    private static final String PROXY_AUTH_ERROR = "Received HTTP_PROXY_AUTH (407) code while not using proxy";
    private HttpHeaders headers;
    private GZIPInputStream compressedBody;

    public OkHttpClientResponse(HttpURLConnection connection) {
    this.connection = connection;
    }

    private int handleIOException(IOException ex) throws IOException {
    if (AUTH_ERROR.equals(ex.getMessage()) || AUTH_ERROR_JELLY_BEAN.equals(ex.getMessage())) {
    return HttpStatus.UNAUTHORIZED.value();
    } else if (PROXY_AUTH_ERROR.equals(ex.getMessage())) {
    return HttpStatus.PROXY_AUTHENTICATION_REQUIRED.value();
    } else {
    throw ex;
    }
    }

    @Override
    public InputStream getBody() throws IOException {
    InputStream errorStream = this.connection.getErrorStream();
    InputStream body = (errorStream != null ? errorStream : this.connection.getInputStream());

    if (isCompressed()) {
    return getCompressedBody(body);
    }
    return body;
    }

    @Override
    public HttpHeaders getHeaders() {
    if (this.headers == null) {
    this.headers = new HttpHeaders();
    // Header field 0 is the status line for most HttpURLConnections, but not on GAE
    String name = this.connection.getHeaderFieldKey(0);
    if (StringUtils.hasLength(name)) {
    this.headers.add(name, this.connection.getHeaderField(0));
    }
    int i = 1;
    while (true) {
    name = this.connection.getHeaderFieldKey(i);
    if (!StringUtils.hasLength(name)) {
    break;
    }
    this.headers.add(name, this.connection.getHeaderField(i));
    i++;
    }
    }
    return this.headers;
    }

    @Override
    public int getRawStatusCode() throws IOException {
    try {
    return this.connection.getResponseCode();
    } catch (IOException ex) {
    return handleIOException(ex);
    }
    }

    @Override
    public HttpStatus getStatusCode() throws IOException {
    return HttpStatus.valueOf(getRawStatusCode());
    }

    @Override
    public String getStatusText() throws IOException {
    try {
    return this.connection.getResponseMessage();
    } catch (IOException ex) {
    return HttpStatus.valueOf(handleIOException(ex)).getReasonPhrase();
    }
    }

    @Override
    public void close() {
    if (this.compressedBody != null) {
    try {
    this.compressedBody.close();
    } catch (IOException e) {
    // ignore
    }
    }
    this.connection.disconnect();
    }

    private boolean isCompressed() {
    List<ContentCodingType> contentCodingTypes = this.getHeaders().getContentEncoding();
    for (ContentCodingType contentCodingType : contentCodingTypes) {
    if (contentCodingType.equals(ContentCodingType.GZIP)) {
    return true;
    }
    }
    return false;
    }

    private InputStream getCompressedBody(InputStream body) throws IOException {
    if (this.compressedBody == null) {
    this.compressedBody = new GZIPInputStream(body);
    }
    return this.compressedBody;
    }
    }
    58 changes: 58 additions & 0 deletions OkHttpFactory.java
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,58 @@
    import java.io.IOException;
    import java.net.HttpURLConnection;
    import java.net.Proxy;
    import java.net.URI;

    import org.springframework.http.HttpMethod;
    import org.springframework.http.client.ClientHttpRequest;
    import org.springframework.http.client.ClientHttpRequestFactory;

    import com.squareup.okhttp.OkHttpClient;

    public class OkHttpFactory implements ClientHttpRequestFactory {

    private final OkHttpClient client = new OkHttpClient();
    private int connectTimeout = -1;
    private int readTimeout = -1;

    @Override
    public ClientHttpRequest createRequest(final URI uri, final HttpMethod httpMethod) throws IOException {
    final HttpURLConnection connection = this.client.open(uri.toURL());
    prepareConnection(connection, httpMethod.name());

    return new OkHttpClientRequest(connection);
    }

    public void setProxy(Proxy proxy) {
    this.client.setProxy(proxy);
    }

    public void setConnectTimeout(int connectTimeout) {
    this.connectTimeout = connectTimeout;
    }

    public void setReadTimeout(int readTimeout) {
    this.readTimeout = readTimeout;
    }

    protected void prepareConnection(HttpURLConnection connection, String httpMethod) throws IOException {
    if (this.connectTimeout >= 0) {
    connection.setConnectTimeout(this.connectTimeout);
    }
    if (this.readTimeout >= 0) {
    connection.setReadTimeout(this.readTimeout);
    }
    connection.setDoInput(true);
    if ("GET".equals(httpMethod)) {
    connection.setInstanceFollowRedirects(true);
    } else {
    connection.setInstanceFollowRedirects(false);
    }
    if ("PUT".equals(httpMethod) || "POST".equals(httpMethod)) {
    connection.setDoOutput(true);
    } else {
    connection.setDoOutput(false);
    }
    connection.setRequestMethod(httpMethod);
    }
    }