/* | |
* Copyright (C) 2013 Square, Inc. | |
* | |
* Licensed under the Apache License, Version 2.0 (the "License"); | |
* you may not use this file except in compliance with the License. | |
* You may obtain a copy of the License at | |
* | |
* http://www.apache.org/licenses/LICENSE-2.0 | |
* | |
* Unless required by applicable law or agreed to in writing, software | |
* distributed under the License is distributed on an "AS IS" BASIS, | |
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
* See the License for the specific language governing permissions and | |
* limitations under the License. | |
*/ | |
import java.io.IOException; | |
import java.net.InetSocketAddress; | |
import java.net.Proxy; | |
import okhttp3.Headers; | |
import okhttp3.MediaType; | |
import okhttp3.OkHttpClient; | |
import okhttp3.Request; | |
import okhttp3.RequestBody; | |
import okhttp3.Response; | |
import okhttp3.ResponseBody; | |
import okhttp3.internal.Util; | |
import okio.BufferedSink; | |
import org.apache.http.Header; | |
import org.apache.http.HttpEntity; | |
import org.apache.http.HttpEntityEnclosingRequest; | |
import org.apache.http.HttpHost; | |
import org.apache.http.HttpRequest; | |
import org.apache.http.HttpResponse; | |
import org.apache.http.RequestLine; | |
import org.apache.http.client.HttpClient; | |
import org.apache.http.client.ResponseHandler; | |
import org.apache.http.client.methods.HttpUriRequest; | |
import org.apache.http.conn.ClientConnectionManager; | |
import org.apache.http.conn.params.ConnRouteParams; | |
import org.apache.http.entity.InputStreamEntity; | |
import org.apache.http.message.BasicHttpResponse; | |
import org.apache.http.params.AbstractHttpParams; | |
import org.apache.http.params.HttpParams; | |
import org.apache.http.protocol.HttpContext; | |
import static java.net.Proxy.Type.HTTP; | |
import static org.apache.http.HttpVersion.HTTP_1_1; | |
/** | |
* OkHttp 3.14 dropped support for the long-deprecated OkApacheClient class, which allows you to use | |
* the Apache HTTP client API with OkHttp's implementation. This class does the same thing using | |
* only public APIs in OkHttp. | |
* | |
* <p>Rather than pasting this 250 line gist into your source code, please upgrade to OkHttp's | |
* request/response API. Your code will be shorter, easier to read, and you'll be able to use | |
* interceptors. | |
*/ | |
public final class ObsoleteApacheClient implements HttpClient { | |
private static Request transformRequest(HttpRequest request) { | |
Request.Builder builder = new Request.Builder(); | |
RequestLine requestLine = request.getRequestLine(); | |
String method = requestLine.getMethod(); | |
builder.url(requestLine.getUri()); | |
String contentType = null; | |
for (Header header : request.getAllHeaders()) { | |
String name = header.getName(); | |
if ("Content-Type".equalsIgnoreCase(name)) { | |
contentType = header.getValue(); | |
} else { | |
builder.header(name, header.getValue()); | |
} | |
} | |
RequestBody body = null; | |
if (request instanceof HttpEntityEnclosingRequest) { | |
HttpEntity entity = ((HttpEntityEnclosingRequest) request).getEntity(); | |
if (entity != null) { | |
// Wrap the entity in a custom Body which takes care of the content, length, and type. | |
body = new HttpEntityBody(entity, contentType); | |
Header encoding = entity.getContentEncoding(); | |
if (encoding != null) { | |
builder.header(encoding.getName(), encoding.getValue()); | |
} | |
} else { | |
body = Util.EMPTY_REQUEST; | |
} | |
} | |
builder.method(method, body); | |
return builder.build(); | |
} | |
private static HttpResponse transformResponse(Response response) { | |
int code = response.code(); | |
String message = response.message(); | |
BasicHttpResponse httpResponse = new BasicHttpResponse(HTTP_1_1, code, message); | |
ResponseBody body = response.body(); | |
InputStreamEntity entity = new InputStreamEntity(body.byteStream(), body.contentLength()); | |
httpResponse.setEntity(entity); | |
Headers headers = response.headers(); | |
for (int i = 0, size = headers.size(); i < size; i++) { | |
String name = headers.name(i); | |
String value = headers.value(i); | |
httpResponse.addHeader(name, value); | |
if ("Content-Type".equalsIgnoreCase(name)) { | |
entity.setContentType(value); | |
} else if ("Content-Encoding".equalsIgnoreCase(name)) { | |
entity.setContentEncoding(value); | |
} | |
} | |
return httpResponse; | |
} | |
private final HttpParams params = new AbstractHttpParams() { | |
@Override public Object getParameter(String name) { | |
if (name.equals(ConnRouteParams.DEFAULT_PROXY)) { | |
Proxy proxy = client.proxy(); | |
if (proxy == null) { | |
return null; | |
} | |
InetSocketAddress address = (InetSocketAddress) proxy.address(); | |
return new HttpHost(address.getHostName(), address.getPort()); | |
} | |
throw new IllegalArgumentException(name); | |
} | |
@Override public HttpParams setParameter(String name, Object value) { | |
if (name.equals(ConnRouteParams.DEFAULT_PROXY)) { | |
HttpHost host = (HttpHost) value; | |
Proxy proxy = null; | |
if (host != null) { | |
proxy = new Proxy(HTTP, new InetSocketAddress(host.getHostName(), host.getPort())); | |
} | |
client = client.newBuilder() | |
.proxy(proxy) | |
.build(); | |
return this; | |
} | |
throw new IllegalArgumentException(name); | |
} | |
@Override public HttpParams copy() { | |
throw new UnsupportedOperationException(); | |
} | |
@Override public boolean removeParameter(String name) { | |
throw new UnsupportedOperationException(); | |
} | |
}; | |
private OkHttpClient client; | |
public ObsoleteApacheClient() { | |
this(new OkHttpClient()); | |
} | |
public ObsoleteApacheClient(OkHttpClient client) { | |
this.client = client; | |
} | |
@Override public HttpParams getParams() { | |
return params; | |
} | |
@Override public ClientConnectionManager getConnectionManager() { | |
throw new UnsupportedOperationException(); | |
} | |
@Override public HttpResponse execute(HttpUriRequest request) throws IOException { | |
return execute(null, request, (HttpContext) null); | |
} | |
@Override public HttpResponse execute(HttpUriRequest request, HttpContext context) | |
throws IOException { | |
return execute(null, request, context); | |
} | |
@Override public HttpResponse execute(HttpHost host, HttpRequest request) throws IOException { | |
return execute(host, request, (HttpContext) null); | |
} | |
@Override public HttpResponse execute(HttpHost host, HttpRequest request, HttpContext context) | |
throws IOException { | |
Request okRequest = transformRequest(request); | |
Response okResponse = client.newCall(okRequest).execute(); | |
return transformResponse(okResponse); | |
} | |
@Override public <T> T execute(HttpUriRequest request, ResponseHandler<? extends T> handler) | |
throws IOException { | |
return execute(null, request, handler, null); | |
} | |
@Override public <T> T execute(HttpUriRequest request, ResponseHandler<? extends T> handler, | |
HttpContext context) throws IOException { | |
return execute(null, request, handler, context); | |
} | |
@Override public <T> T execute(HttpHost host, HttpRequest request, | |
ResponseHandler<? extends T> handler) throws IOException { | |
return execute(host, request, handler, null); | |
} | |
@Override public <T> T execute(HttpHost host, HttpRequest request, | |
ResponseHandler<? extends T> handler, HttpContext context) throws IOException { | |
HttpResponse response = execute(host, request, context); | |
try { | |
return handler.handleResponse(response); | |
} finally { | |
consumeContentQuietly(response); | |
} | |
} | |
private static void consumeContentQuietly(HttpResponse response) { | |
try { | |
response.getEntity().consumeContent(); | |
} catch (Throwable ignored) { | |
} | |
} | |
/** Adapts an {@link HttpEntity} to OkHttp's {@link RequestBody}. */ | |
static final class HttpEntityBody extends RequestBody { | |
static final MediaType DEFAULT_MEDIA_TYPE = MediaType.get("application/octet-stream"); | |
final HttpEntity entity; | |
final MediaType mediaType; | |
HttpEntityBody(HttpEntity entity, String contentTypeHeader) { | |
this.entity = entity; | |
if (contentTypeHeader != null) { | |
mediaType = MediaType.parse(contentTypeHeader); | |
} else if (entity.getContentType() != null) { | |
mediaType = MediaType.parse(entity.getContentType().getValue()); | |
} else { | |
// Apache is forgiving and lets you skip specifying a content type with an entity. OkHttp is | |
// not forgiving so we fall back to a generic type if it's missing. | |
mediaType = DEFAULT_MEDIA_TYPE; | |
} | |
} | |
@Override public long contentLength() { | |
return entity.getContentLength(); | |
} | |
@Override public MediaType contentType() { | |
return mediaType; | |
} | |
@Override public void writeTo(BufferedSink sink) throws IOException { | |
entity.writeTo(sink.outputStream()); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment