package com.orhanobut.wasp; import com.android.volley.AuthFailureError; import com.android.volley.Request; import com.android.volley.toolbox.HttpStack; import com.squareup.okhttp.Call; import com.squareup.okhttp.Headers; import com.squareup.okhttp.MediaType; import com.squareup.okhttp.OkHttpClient; import com.squareup.okhttp.Protocol; import com.squareup.okhttp.RequestBody; import com.squareup.okhttp.Response; import com.squareup.okhttp.ResponseBody; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.ProtocolVersion; import org.apache.http.StatusLine; import org.apache.http.entity.BasicHttpEntity; import org.apache.http.message.BasicHeader; import org.apache.http.message.BasicHttpResponse; import org.apache.http.message.BasicStatusLine; import java.io.IOException; import java.util.Map; import java.util.concurrent.TimeUnit; /** * An HttpStack implementation which uses {@link com.squareup.okhttp.OkHttpClient} as http client */ class OkHttpStack implements HttpStack { private final OkHttpClient client; OkHttpStack(OkHttpClient client) { this.client = client; } OkHttpClient getClient() { return client; } @Override public HttpResponse performRequest(Request<?> request, Map<String, String> additionalHeaders) throws IOException, AuthFailureError { OkHttpClient okHttpClient = client.clone(); int timeoutMs = request.getTimeoutMs(); okHttpClient.setConnectTimeout(timeoutMs, TimeUnit.MILLISECONDS); okHttpClient.setReadTimeout(timeoutMs, TimeUnit.MILLISECONDS); okHttpClient.setWriteTimeout(timeoutMs, TimeUnit.MILLISECONDS); com.squareup.okhttp.Request.Builder builder = new com.squareup.okhttp.Request.Builder(); builder.url(request.getUrl()); Map<String, String> headers = request.getHeaders(); for (String name : headers.keySet()) { builder.addHeader(name, headers.get(name)); } for (String name : additionalHeaders.keySet()) { builder.addHeader(name, additionalHeaders.get(name)); } setConnectionParametersForRequest(builder, request); Call okHttpCall = okHttpClient.newCall(builder.build()); Response okHttpResponse = okHttpCall.execute(); StatusLine responseStatus = new BasicStatusLine( parseProtocol(okHttpResponse.protocol()), okHttpResponse.code(), okHttpResponse.message() ); BasicHttpResponse response = new BasicHttpResponse(responseStatus); response.setEntity(entityFromOkHttpResponse(okHttpResponse)); Headers responseHeaders = okHttpResponse.headers(); for (int i = 0, len = responseHeaders.size(); i < len; i++) { String name = responseHeaders.name(i), value = responseHeaders.value(i); if (name != null) { response.addHeader(new BasicHeader(name, value)); } } return response; } private static HttpEntity entityFromOkHttpResponse(Response response) throws IOException { BasicHttpEntity entity = new BasicHttpEntity(); ResponseBody body = response.body(); entity.setContent(body.byteStream()); entity.setContentLength(body.contentLength()); entity.setContentEncoding(response.header("Content-Encoding")); if (body.contentType() != null) { entity.setContentType(body.contentType().type()); } return entity; } private static void setConnectionParametersForRequest( com.squareup.okhttp.Request.Builder builder, Request<?> request) throws IOException, AuthFailureError { switch (request.getMethod()) { case Request.Method.DEPRECATED_GET_OR_POST: // Ensure backwards compatibility. Volley assumes a request with a null body is a GET. byte[] postBody = request.getPostBody(); if (postBody != null) { builder.post(RequestBody.create( MediaType.parse(request.getPostBodyContentType()), postBody )); } break; case Request.Method.GET: builder.get(); break; case Request.Method.DELETE: builder.delete(); break; case Request.Method.POST: builder.post(createRequestBody(request)); break; case Request.Method.PUT: builder.put(createRequestBody(request)); break; case Request.Method.HEAD: builder.head(); break; case Request.Method.OPTIONS: builder.method("OPTIONS", null); break; case Request.Method.TRACE: builder.method("TRACE", null); break; case Request.Method.PATCH: builder.patch(createRequestBody(request)); break; default: throw new IllegalStateException("Unknown method type."); } } private static ProtocolVersion parseProtocol(final Protocol protocol) { switch (protocol) { case HTTP_1_0: return new ProtocolVersion("HTTP", 1, 0); case HTTP_1_1: return new ProtocolVersion("HTTP", 1, 1); case SPDY_3: return new ProtocolVersion("SPDY", 3, 1); case HTTP_2: return new ProtocolVersion("HTTP", 2, 0); default: throw new IllegalAccessError("Unkwown protocol"); } } private static RequestBody createRequestBody(Request request) throws AuthFailureError { byte[] body = request.getBody(); if (body == null) { return null; } return RequestBody.create(MediaType.parse(request.getBodyContentType()), body); } }