Home | History | Annotate | Download | only in apache
      1 // Copyright 2013 Square, Inc.
      2 package com.squareup.okhttp.apache;
      3 
      4 import com.squareup.okhttp.Headers;
      5 import com.squareup.okhttp.OkHttpClient;
      6 import com.squareup.okhttp.Request;
      7 import com.squareup.okhttp.RequestBody;
      8 import com.squareup.okhttp.Response;
      9 import com.squareup.okhttp.ResponseBody;
     10 import java.io.IOException;
     11 import java.net.InetSocketAddress;
     12 import java.net.Proxy;
     13 import org.apache.http.Header;
     14 import org.apache.http.HttpEntity;
     15 import org.apache.http.HttpEntityEnclosingRequest;
     16 import org.apache.http.HttpHost;
     17 import org.apache.http.HttpRequest;
     18 import org.apache.http.HttpResponse;
     19 import org.apache.http.RequestLine;
     20 import org.apache.http.client.HttpClient;
     21 import org.apache.http.client.ResponseHandler;
     22 import org.apache.http.client.methods.HttpUriRequest;
     23 import org.apache.http.conn.ClientConnectionManager;
     24 import org.apache.http.conn.params.ConnRouteParams;
     25 import org.apache.http.entity.InputStreamEntity;
     26 import org.apache.http.message.BasicHttpResponse;
     27 import org.apache.http.params.AbstractHttpParams;
     28 import org.apache.http.params.HttpParams;
     29 import org.apache.http.protocol.HttpContext;
     30 
     31 import static java.net.Proxy.Type.HTTP;
     32 import static org.apache.http.HttpVersion.HTTP_1_1;
     33 
     34 /**
     35  * Implements Apache's {@link HttpClient} API using {@link OkHttpClient}.
     36  * <p>
     37  * <strong>Warning:</strong> Many core features of Apache HTTP client are not implemented by this
     38  * API. This includes the keep-alive strategy, cookie store, credentials provider, route planner
     39  * and others.
     40  */
     41 public final class OkApacheClient implements HttpClient {
     42   private static Request transformRequest(HttpRequest request) {
     43     Request.Builder builder = new Request.Builder();
     44 
     45     RequestLine requestLine = request.getRequestLine();
     46     String method = requestLine.getMethod();
     47     builder.url(requestLine.getUri());
     48 
     49     String contentType = null;
     50     for (Header header : request.getAllHeaders()) {
     51       String name = header.getName();
     52       if ("Content-Type".equalsIgnoreCase(name)) {
     53         contentType = header.getValue();
     54       } else {
     55         builder.header(name, header.getValue());
     56       }
     57     }
     58 
     59     RequestBody body = null;
     60     if (request instanceof HttpEntityEnclosingRequest) {
     61       HttpEntity entity = ((HttpEntityEnclosingRequest) request).getEntity();
     62       if (entity != null) {
     63         // Wrap the entity in a custom Body which takes care of the content, length, and type.
     64         body = new HttpEntityBody(entity, contentType);
     65 
     66         Header encoding = entity.getContentEncoding();
     67         if (encoding != null) {
     68           builder.header(encoding.getName(), encoding.getValue());
     69         }
     70       } else {
     71         body = RequestBody.create(null, new byte[0]);
     72       }
     73     }
     74     builder.method(method, body);
     75 
     76     return builder.build();
     77   }
     78 
     79   private static HttpResponse transformResponse(Response response) throws IOException {
     80     int code = response.code();
     81     String message = response.message();
     82     BasicHttpResponse httpResponse = new BasicHttpResponse(HTTP_1_1, code, message);
     83 
     84     ResponseBody body = response.body();
     85     InputStreamEntity entity = new InputStreamEntity(body.byteStream(), body.contentLength());
     86     httpResponse.setEntity(entity);
     87 
     88     Headers headers = response.headers();
     89     for (int i = 0, size = headers.size(); i < size; i++) {
     90       String name = headers.name(i);
     91       String value = headers.value(i);
     92       httpResponse.addHeader(name, value);
     93       if ("Content-Type".equalsIgnoreCase(name)) {
     94         entity.setContentType(value);
     95       } else if ("Content-Encoding".equalsIgnoreCase(name)) {
     96         entity.setContentEncoding(value);
     97       }
     98     }
     99 
    100     return httpResponse;
    101   }
    102 
    103   private final HttpParams params = new AbstractHttpParams() {
    104     @Override public Object getParameter(String name) {
    105       if (name.equals(ConnRouteParams.DEFAULT_PROXY)) {
    106         Proxy proxy = client.getProxy();
    107         if (proxy == null) {
    108           return null;
    109         }
    110         InetSocketAddress address = (InetSocketAddress) proxy.address();
    111         return new HttpHost(address.getHostName(), address.getPort());
    112       }
    113       throw new IllegalArgumentException(name);
    114     }
    115 
    116     @Override public HttpParams setParameter(String name, Object value) {
    117       if (name.equals(ConnRouteParams.DEFAULT_PROXY)) {
    118         HttpHost host = (HttpHost) value;
    119         Proxy proxy = null;
    120         if (host != null) {
    121           proxy = new Proxy(HTTP, new InetSocketAddress(host.getHostName(), host.getPort()));
    122         }
    123         client.setProxy(proxy);
    124         return this;
    125       }
    126       throw new IllegalArgumentException(name);
    127     }
    128 
    129     @Override public HttpParams copy() {
    130       throw new UnsupportedOperationException();
    131     }
    132 
    133     @Override public boolean removeParameter(String name) {
    134       throw new UnsupportedOperationException();
    135     }
    136   };
    137 
    138   private final OkHttpClient client;
    139 
    140   public OkApacheClient() {
    141     this(new OkHttpClient());
    142   }
    143 
    144   public OkApacheClient(OkHttpClient client) {
    145     this.client = client;
    146   }
    147 
    148   @Override public HttpParams getParams() {
    149     return params;
    150   }
    151 
    152   @Override public ClientConnectionManager getConnectionManager() {
    153     throw new UnsupportedOperationException();
    154   }
    155 
    156   @Override public HttpResponse execute(HttpUriRequest request) throws IOException {
    157     return execute(null, request, (HttpContext) null);
    158   }
    159 
    160   @Override public HttpResponse execute(HttpUriRequest request, HttpContext context)
    161       throws IOException {
    162     return execute(null, request, context);
    163   }
    164 
    165   @Override public HttpResponse execute(HttpHost host, HttpRequest request) throws IOException {
    166     return execute(host, request, (HttpContext) null);
    167   }
    168 
    169   @Override public HttpResponse execute(HttpHost host, HttpRequest request, HttpContext context)
    170       throws IOException {
    171     Request okRequest = transformRequest(request);
    172     Response okResponse = client.newCall(okRequest).execute();
    173     return transformResponse(okResponse);
    174   }
    175 
    176   @Override public <T> T execute(HttpUriRequest request, ResponseHandler<? extends T> handler)
    177       throws IOException {
    178     return execute(null, request, handler, null);
    179   }
    180 
    181   @Override public <T> T execute(HttpUriRequest request, ResponseHandler<? extends T> handler,
    182       HttpContext context) throws IOException {
    183     return execute(null, request, handler, context);
    184   }
    185 
    186   @Override public <T> T execute(HttpHost host, HttpRequest request,
    187       ResponseHandler<? extends T> handler) throws IOException {
    188     return execute(host, request, handler, null);
    189   }
    190 
    191   @Override public <T> T execute(HttpHost host, HttpRequest request,
    192       ResponseHandler<? extends T> handler, HttpContext context) throws IOException {
    193     HttpResponse response = execute(host, request, context);
    194     try {
    195       return handler.handleResponse(response);
    196     } finally {
    197       consumeContentQuietly(response);
    198     }
    199   }
    200 
    201   private static void consumeContentQuietly(HttpResponse response) {
    202     try {
    203       response.getEntity().consumeContent();
    204     } catch (Throwable ignored) {
    205     }
    206   }
    207 }
    208