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       }
     71     }
     72     builder.method(method, body);
     73 
     74     return builder.build();
     75   }
     76 
     77   private static HttpResponse transformResponse(Response response) throws IOException {
     78     int code = response.code();
     79     String message = response.message();
     80     BasicHttpResponse httpResponse = new BasicHttpResponse(HTTP_1_1, code, message);
     81 
     82     ResponseBody body = response.body();
     83     InputStreamEntity entity = new InputStreamEntity(body.byteStream(), body.contentLength());
     84     httpResponse.setEntity(entity);
     85 
     86     Headers headers = response.headers();
     87     for (int i = 0, size = headers.size(); i < size; i++) {
     88       String name = headers.name(i);
     89       String value = headers.value(i);
     90       httpResponse.addHeader(name, value);
     91       if ("Content-Type".equalsIgnoreCase(name)) {
     92         entity.setContentType(value);
     93       } else if ("Content-Encoding".equalsIgnoreCase(name)) {
     94         entity.setContentEncoding(value);
     95       }
     96     }
     97 
     98     return httpResponse;
     99   }
    100 
    101   private final HttpParams params = new AbstractHttpParams() {
    102     @Override public Object getParameter(String name) {
    103       if (name.equals(ConnRouteParams.DEFAULT_PROXY)) {
    104         Proxy proxy = client.getProxy();
    105         if (proxy == null) {
    106           return null;
    107         }
    108         InetSocketAddress address = (InetSocketAddress) proxy.address();
    109         return new HttpHost(address.getHostName(), address.getPort());
    110       }
    111       throw new IllegalArgumentException(name);
    112     }
    113 
    114     @Override public HttpParams setParameter(String name, Object value) {
    115       if (name.equals(ConnRouteParams.DEFAULT_PROXY)) {
    116         HttpHost host = (HttpHost) value;
    117         Proxy proxy = null;
    118         if (host != null) {
    119           proxy = new Proxy(HTTP, new InetSocketAddress(host.getHostName(), host.getPort()));
    120         }
    121         client.setProxy(proxy);
    122         return this;
    123       }
    124       throw new IllegalArgumentException(name);
    125     }
    126 
    127     @Override public HttpParams copy() {
    128       throw new UnsupportedOperationException();
    129     }
    130 
    131     @Override public boolean removeParameter(String name) {
    132       throw new UnsupportedOperationException();
    133     }
    134   };
    135 
    136   private final OkHttpClient client;
    137 
    138   public OkApacheClient() {
    139     this(new OkHttpClient());
    140   }
    141 
    142   public OkApacheClient(OkHttpClient client) {
    143     this.client = client;
    144   }
    145 
    146   @Override public HttpParams getParams() {
    147     return params;
    148   }
    149 
    150   @Override public ClientConnectionManager getConnectionManager() {
    151     throw new UnsupportedOperationException();
    152   }
    153 
    154   @Override public HttpResponse execute(HttpUriRequest request) throws IOException {
    155     return execute(null, request, (HttpContext) null);
    156   }
    157 
    158   @Override public HttpResponse execute(HttpUriRequest request, HttpContext context)
    159       throws IOException {
    160     return execute(null, request, context);
    161   }
    162 
    163   @Override public HttpResponse execute(HttpHost host, HttpRequest request) throws IOException {
    164     return execute(host, request, (HttpContext) null);
    165   }
    166 
    167   @Override public HttpResponse execute(HttpHost host, HttpRequest request, HttpContext context)
    168       throws IOException {
    169     Request okRequest = transformRequest(request);
    170     Response okResponse = client.newCall(okRequest).execute();
    171     return transformResponse(okResponse);
    172   }
    173 
    174   @Override public <T> T execute(HttpUriRequest request, ResponseHandler<? extends T> handler)
    175       throws IOException {
    176     return execute(null, request, handler, null);
    177   }
    178 
    179   @Override public <T> T execute(HttpUriRequest request, ResponseHandler<? extends T> handler,
    180       HttpContext context) throws IOException {
    181     return execute(null, request, handler, context);
    182   }
    183 
    184   @Override public <T> T execute(HttpHost host, HttpRequest request,
    185       ResponseHandler<? extends T> handler) throws IOException {
    186     return execute(host, request, handler, null);
    187   }
    188 
    189   @Override public <T> T execute(HttpHost host, HttpRequest request,
    190       ResponseHandler<? extends T> handler, HttpContext context) throws IOException {
    191     HttpResponse response = execute(host, request, context);
    192     try {
    193       return handler.handleResponse(response);
    194     } finally {
    195       consumeContentQuietly(response);
    196     }
    197   }
    198 
    199   private static void consumeContentQuietly(HttpResponse response) {
    200     try {
    201       response.getEntity().consumeContent();
    202     } catch (Throwable ignored) {
    203     }
    204   }
    205 }
    206