Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
An OkHttp backed HttpStack for Volley (okhttp3 version)
/**
* The MIT License (MIT)
*
* Copyright (c) 2015 Circle Internet Financial
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.circle.android.api;
import com.android.volley.AuthFailureError;
import com.android.volley.Request;
import com.android.volley.toolbox.HttpStack;
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;
import okhttp3.Call;
import okhttp3.Headers;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Protocol;
import okhttp3.RequestBody;
import okhttp3.Response;
import okhttp3.ResponseBody;
/**
* OkHttp backed {@link com.android.volley.toolbox.HttpStack HttpStack} that does not
* use okhttp-urlconnection
*/
public class OkHttp3Stack implements HttpStack {
public OkHttp3Stack() {
}
@Override
public HttpResponse performRequest(com.android.volley.Request<?> request, Map<String, String> additionalHeaders)
throws IOException, AuthFailureError {
OkHttpClient.Builder clientBuilder = new OkHttpClient.Builder();
int timeoutMs = request.getTimeoutMs();
clientBuilder.connectTimeout(timeoutMs, TimeUnit.MILLISECONDS);
clientBuilder.readTimeout(timeoutMs, TimeUnit.MILLISECONDS);
clientBuilder.writeTimeout(timeoutMs, TimeUnit.MILLISECONDS);
okhttp3.Request.Builder okHttpRequestBuilder = new okhttp3.Request.Builder();
okHttpRequestBuilder.url(request.getUrl());
Map<String, String> headers = request.getHeaders();
for(final String name : headers.keySet()) {
okHttpRequestBuilder.addHeader(name, headers.get(name));
}
for(final String name : additionalHeaders.keySet()) {
okHttpRequestBuilder.addHeader(name, additionalHeaders.get(name));
}
setConnectionParametersForRequest(okHttpRequestBuilder, request);
OkHttpClient client = clientBuilder.build();
okhttp3.Request okHttpRequest = okHttpRequestBuilder.build();
Call okHttpCall = client.newCall(okHttpRequest);
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++) {
final 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 r) throws IOException {
BasicHttpEntity entity = new BasicHttpEntity();
ResponseBody body = r.body();
entity.setContent(body.byteStream());
entity.setContentLength(body.contentLength());
entity.setContentEncoding(r.header("Content-Encoding"));
if (body.contentType() != null) {
entity.setContentType(body.contentType().type());
}
return entity;
}
@SuppressWarnings("deprecation")
private static void setConnectionParametersForRequest(okhttp3.Request.Builder builder, com.android.volley.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 p) {
switch (p) {
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);
}
throw new IllegalAccessError("Unkwown protocol");
}
private static RequestBody createRequestBody(Request r) throws AuthFailureError {
final byte[] body = r.getBody();
if (body == null) {
return null;
}
return RequestBody.create(MediaType.parse(r.getBodyContentType()), body);
}
}
@JustSayBien

This comment has been minimized.

Copy link

commented Apr 10, 2016

Thanks for sharing. As improvement an OkHttpClient instance can be hold as member and you can call client.newBuilder() for each request. This way you would not create a new connection pool for every request, but reuse the existing one (See https://github.com/square/okhttp/blob/master/CHANGELOG.md Version 3.0.0-RC1)

@amadib

This comment has been minimized.

Copy link

commented May 8, 2016

@JustSayBien meaning we create a client in the OkHttp3Stack constructor with and always call mClient.newBuilder()?

I'm doing this to be able to inspect through Stetho. How will I add the interceptors now?

@wanghuabing

This comment has been minimized.

Copy link

commented Jun 6, 2016

Thanks

@kkkkkkirs

This comment has been minimized.

Copy link

commented Jun 16, 2016

but,can't support https

@loveanao

This comment has been minimized.

Copy link

commented Sep 30, 2016

thanks for sharing

@thomaszheng

This comment has been minimized.

Copy link

commented Nov 3, 2016

it use org.apache.http as protocol ,eg:org.apache.http.HttpResponse.if i want to use volley based on okhttp, i must import httpcore.jar. it has methods to avoid?

@intari

This comment has been minimized.

Copy link

commented Feb 22, 2017

@amadib
I use slightly modified version of this class from https://gist.github.com/intari/e57a945eed9c2ee0f9eb9082469698f3 for Stetho

@minas1

This comment has been minimized.

Copy link

commented Jul 28, 2017

Do I have to include any library in gradle for org.apache.http.* classes?

@minion06

This comment has been minimized.

Copy link

commented Jan 31, 2018

The org.apache.http is available if we are targeting from version 17. How about if we are targeting v 21 and above?

@LOG-TAG

This comment has been minimized.

Copy link

commented Mar 2, 2018

how can we use this when we have
compile('com.google.api-client:google-api-client-gson:1.19.1') { exclude(group: 'com.google.android', module: 'android') exclude(group: 'org.apache.httpcomponents', module: 'httpclient') }

in the app dependency? !! no replacement for this ?
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

?

@LOG-TAG

This comment has been minimized.

@LOG-TAG

This comment has been minimized.

Copy link

commented Mar 3, 2018

@intari @alashow thanks here is the updated version of latest volley 1.1.0 https://gist.github.com/LOG-TAG/3ad1c191b3ca7eab3ea6834386e30eb9 by removing all deprecated org.apache dependencies!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.