mirror of
https://github.com/etesync/android
synced 2025-02-02 02:41:31 +00:00
Upgrade to okhttp3
This commit is contained in:
parent
ba0350c83d
commit
89050d88c6
@ -68,7 +68,7 @@ dependencies {
|
||||
|
||||
compile project(':MemorizingTrustManager')
|
||||
|
||||
androidTestCompile 'com.squareup.okhttp:mockwebserver:2.7.2'
|
||||
androidTestCompile 'com.squareup.okhttp3:mockwebserver:3.0.1+'
|
||||
compile 'dnsjava:dnsjava:2.1.7'
|
||||
compile 'org.apache.commons:commons-lang3:3.4'
|
||||
compile 'org.slf4j:slf4j-android:1.7.13'
|
||||
|
@ -10,13 +10,14 @@ package at.bitfire.davdroid;
|
||||
|
||||
import android.test.InstrumentationTestCase;
|
||||
|
||||
import com.squareup.okhttp.ConnectionSpec;
|
||||
import com.squareup.okhttp.HttpUrl;
|
||||
import com.squareup.okhttp.Request;
|
||||
import com.squareup.okhttp.Response;
|
||||
import com.squareup.okhttp.TlsVersion;
|
||||
import com.squareup.okhttp.mockwebserver.MockResponse;
|
||||
import com.squareup.okhttp.mockwebserver.MockWebServer;
|
||||
import okhttp3.ConnectionSpec;
|
||||
import okhttp3.HttpUrl;
|
||||
import okhttp3.OkHttpClient;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.Response;
|
||||
import okhttp3.TlsVersion;
|
||||
import okhttp3.mockwebserver.MockResponse;
|
||||
import okhttp3.mockwebserver.MockWebServer;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URISyntaxException;
|
||||
@ -25,11 +26,11 @@ import java.util.Collections;
|
||||
public class HttpClientTest extends InstrumentationTestCase {
|
||||
|
||||
MockWebServer server;
|
||||
HttpClient httpClient;
|
||||
OkHttpClient httpClient;
|
||||
|
||||
@Override
|
||||
public void setUp() throws IOException {
|
||||
httpClient = new HttpClient(null, getInstrumentation().getTargetContext().getApplicationContext());
|
||||
httpClient = HttpClient.create(getInstrumentation().getTargetContext().getApplicationContext());
|
||||
|
||||
server = new MockWebServer();
|
||||
server.start();
|
||||
@ -64,20 +65,4 @@ public class HttpClientTest extends InstrumentationTestCase {
|
||||
// doesn't work for URLs with ports, see https://code.google.com/p/android/issues/detail?id=193475
|
||||
}
|
||||
|
||||
public void testTLSVersion() throws IOException {
|
||||
server.useHttps(new SSLSocketFactoryCompat(null), false);
|
||||
assertEquals("https", server.url("/").scheme());
|
||||
|
||||
httpClient.setConnectionSpecs(Collections.singletonList(new ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS)
|
||||
.tlsVersions(TlsVersion.TLS_1_2)
|
||||
.build()));
|
||||
|
||||
// FIXME
|
||||
/*server.enqueue(new MockResponse().setResponseCode(204));
|
||||
Response response = httpClient.newCall(new Request.Builder()
|
||||
.get().url(server.url("/"))
|
||||
.build()).execute();
|
||||
assertTrue(response.isSuccessful());*/
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -10,7 +10,7 @@ package at.bitfire.davdroid;
|
||||
|
||||
import android.os.Build;
|
||||
|
||||
import com.squareup.okhttp.mockwebserver.MockWebServer;
|
||||
import okhttp3.mockwebserver.MockWebServer;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
|
@ -2,9 +2,9 @@ package at.bitfire.davdroid.resource;
|
||||
|
||||
import android.test.InstrumentationTestCase;
|
||||
|
||||
import com.squareup.okhttp.HttpUrl;
|
||||
import com.squareup.okhttp.mockwebserver.MockResponse;
|
||||
import com.squareup.okhttp.mockwebserver.MockWebServer;
|
||||
import okhttp3.HttpUrl;
|
||||
import okhttp3.mockwebserver.MockResponse;
|
||||
import okhttp3.mockwebserver.MockWebServer;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
|
@ -11,13 +11,15 @@ package at.bitfire.davdroid;
|
||||
import android.content.Context;
|
||||
import android.os.Build;
|
||||
|
||||
import com.squareup.okhttp.Credentials;
|
||||
import com.squareup.okhttp.Interceptor;
|
||||
import com.squareup.okhttp.OkHttpClient;
|
||||
import com.squareup.okhttp.Request;
|
||||
import com.squareup.okhttp.Response;
|
||||
import com.squareup.okhttp.internal.tls.OkHostnameVerifier;
|
||||
import com.squareup.okhttp.logging.HttpLoggingInterceptor;
|
||||
import lombok.NonNull;
|
||||
import okhttp3.CookieJar;
|
||||
import okhttp3.Credentials;
|
||||
import okhttp3.Interceptor;
|
||||
import okhttp3.OkHttpClient;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.Response;
|
||||
import okhttp3.internal.tls.OkHostnameVerifier;
|
||||
import okhttp3.logging.HttpLoggingInterceptor;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
|
||||
@ -34,49 +36,84 @@ import at.bitfire.dav4android.BasicDigestAuthenticator;
|
||||
import de.duenndns.ssl.MemorizingTrustManager;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
public class HttpClient extends OkHttpClient {
|
||||
private final int MAX_LOG_LINE_LENGTH = 85;
|
||||
public class HttpClient {
|
||||
private static final int MAX_LOG_LINE_LENGTH = 85;
|
||||
|
||||
final static UserAgentInterceptor userAgentInterceptor = new UserAgentInterceptor();
|
||||
private static final OkHttpClient client = new OkHttpClient();
|
||||
private static final UserAgentInterceptor userAgentInterceptor = new UserAgentInterceptor();
|
||||
|
||||
static final String userAgent;
|
||||
private static final String userAgent;
|
||||
static {
|
||||
String date = new SimpleDateFormat("yyyy/MM/dd", Locale.US).format(new Date(BuildConfig.buildTime));
|
||||
userAgent = "DAVdroid/" + BuildConfig.VERSION_NAME + " (" + date + "; dav4android) Android/" + Build.VERSION.RELEASE;
|
||||
userAgent = "DAVdroid/" + BuildConfig.VERSION_NAME + " (" + date + "; dav4android; okhttp3) Android/" + Build.VERSION.RELEASE;
|
||||
}
|
||||
|
||||
final Logger log;
|
||||
final Context context;
|
||||
protected String username, password;
|
||||
private HttpClient() {
|
||||
}
|
||||
|
||||
|
||||
protected HttpClient(Logger log, Context context) {
|
||||
super();
|
||||
this.log = (log != null) ? log : Constants.log;
|
||||
this.context = context;
|
||||
public static OkHttpClient create(Context context) {
|
||||
OkHttpClient.Builder builder = client.newBuilder();
|
||||
|
||||
if (context != null) {
|
||||
// use MemorizingTrustManager to manage self-signed certificates
|
||||
MemorizingTrustManager mtm = new MemorizingTrustManager(context);
|
||||
setSslSocketFactory(new SSLSocketFactoryCompat(mtm));
|
||||
setHostnameVerifier(mtm.wrapHostnameVerifier(OkHostnameVerifier.INSTANCE));
|
||||
builder.sslSocketFactory(new SSLSocketFactoryCompat(mtm));
|
||||
builder.hostnameVerifier(mtm.wrapHostnameVerifier(OkHostnameVerifier.INSTANCE));
|
||||
}
|
||||
|
||||
// set timeouts
|
||||
setConnectTimeout(30, TimeUnit.SECONDS);
|
||||
setWriteTimeout(30, TimeUnit.SECONDS);
|
||||
setReadTimeout(120, TimeUnit.SECONDS);
|
||||
builder.connectTimeout(30, TimeUnit.SECONDS);
|
||||
builder.writeTimeout(30, TimeUnit.SECONDS);
|
||||
builder.readTimeout(120, TimeUnit.SECONDS);
|
||||
|
||||
// don't allow redirects, because it would break PROPFIND handling
|
||||
builder.followRedirects(false);
|
||||
|
||||
// add User-Agent to every request
|
||||
networkInterceptors().add(userAgentInterceptor);
|
||||
builder.addNetworkInterceptor(userAgentInterceptor);
|
||||
|
||||
// add cookie store for non-persistent cookies (some services like Horde use cookies for session tracking)
|
||||
CookieManager cookies = new CookieManager();
|
||||
setCookieHandler(cookies);
|
||||
builder.cookieJar(MemoryCookieStore.INSTANCE);
|
||||
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
public static OkHttpClient addAuthentication(@NonNull OkHttpClient httpClient, @NonNull String username, @NonNull String password, boolean preemptive) {
|
||||
OkHttpClient.Builder builder = httpClient.newBuilder();
|
||||
if (preemptive)
|
||||
builder.addNetworkInterceptor(new PreemptiveAuthenticationInterceptor(username, password));
|
||||
else
|
||||
builder.authenticator(new BasicDigestAuthenticator(null, username, password));
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
public static OkHttpClient addAuthentication(@NonNull OkHttpClient httpClient, @NonNull String host, @NonNull String username, @NonNull String password, boolean preemptive) {
|
||||
return httpClient.newBuilder()
|
||||
.authenticator(new BasicDigestAuthenticator(host, username, password))
|
||||
.build();
|
||||
}
|
||||
|
||||
//@NonNull final Logger log
|
||||
|
||||
/**
|
||||
* Creates a new HttpClient (based on another one) which can be used to download external resources:
|
||||
* 1. it does not use preemptive authentication
|
||||
* 2. it only authenticates against a given host
|
||||
* @param httpClient user name and password from this client will be used
|
||||
* @param host authentication will be restricted to this host
|
||||
*/
|
||||
/*public HttpClient(Logger log, HttpClient client, String host) {
|
||||
this(log, client.context);
|
||||
|
||||
username = client.username;
|
||||
password = client.password;
|
||||
setAuthenticator(new BasicDigestAuthenticator(host, username, password));
|
||||
}*/
|
||||
|
||||
public static OkHttpClient addLogger(@NonNull OkHttpClient httpClient, @NonNull final Logger logger) {
|
||||
// enable verbose logs, if requested
|
||||
if (this.log.isTraceEnabled()) {
|
||||
HttpLoggingInterceptor logger = new HttpLoggingInterceptor(new HttpLoggingInterceptor.Logger() {
|
||||
if (logger.isTraceEnabled()) {
|
||||
HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor(new HttpLoggingInterceptor.Logger() {
|
||||
@Override
|
||||
public void log(String message) {
|
||||
BufferedReader reader = new BufferedReader(new StringReader(message));
|
||||
@ -86,51 +123,23 @@ public class HttpClient extends OkHttpClient {
|
||||
int len = line.length();
|
||||
for (int pos = 0; pos < len; pos += MAX_LOG_LINE_LENGTH)
|
||||
if (pos < len - MAX_LOG_LINE_LENGTH)
|
||||
HttpClient.this.log.trace(line.substring(pos, pos + MAX_LOG_LINE_LENGTH) + "\\");
|
||||
logger.trace(line.substring(pos, pos + MAX_LOG_LINE_LENGTH) + "\\");
|
||||
else
|
||||
HttpClient.this.log.trace(line.substring(pos));
|
||||
logger.trace(line.substring(pos));
|
||||
}
|
||||
} catch(IOException e) {
|
||||
// for some reason, we couldn't split our message
|
||||
HttpClient.this.log.trace(message);
|
||||
logger.trace(message);
|
||||
}
|
||||
}
|
||||
});
|
||||
logger.setLevel(HttpLoggingInterceptor.Level.BODY);
|
||||
interceptors().add(logger);
|
||||
}
|
||||
}
|
||||
loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
|
||||
|
||||
public HttpClient(Logger log, Context context, String username, String password, boolean preemptive) {
|
||||
this(log, context);
|
||||
|
||||
// authentication
|
||||
this.username = username;
|
||||
this.password = password;
|
||||
if (preemptive)
|
||||
networkInterceptors().add(new PreemptiveAuthenticationInterceptor(username, password));
|
||||
else
|
||||
setAuthenticator(new BasicDigestAuthenticator(null, username, password));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new HttpClient (based on another one) which can be used to download external resources:
|
||||
* 1. it does not use preemptive authentication
|
||||
* 2. it only authenticates against a given host
|
||||
* @param client user name and password from this client will be used
|
||||
* @param host authentication will be restricted to this host
|
||||
*/
|
||||
public HttpClient(Logger log, HttpClient client, String host) {
|
||||
this(log, client.context);
|
||||
|
||||
username = client.username;
|
||||
password = client.password;
|
||||
setAuthenticator(new BasicDigestAuthenticator(host, username, password));
|
||||
}
|
||||
|
||||
// for testing (mock server doesn't need auth)
|
||||
public HttpClient() {
|
||||
this(null, null, null, null, false);
|
||||
return httpClient.newBuilder()
|
||||
.addInterceptor(loggingInterceptor)
|
||||
.build();
|
||||
} else
|
||||
return httpClient;
|
||||
}
|
||||
|
||||
|
||||
|
41
app/src/main/java/at/bitfire/davdroid/MemoryCookieStore.java
Normal file
41
app/src/main/java/at/bitfire/davdroid/MemoryCookieStore.java
Normal file
@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright © 2013 – 2016 Ricki Hirner (bitfire web engineering).
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the GNU Public License v3.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.gnu.org/licenses/gpl.html
|
||||
*/
|
||||
|
||||
package at.bitfire.davdroid;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import okhttp3.Cookie;
|
||||
import okhttp3.CookieJar;
|
||||
import okhttp3.HttpUrl;
|
||||
|
||||
/**
|
||||
* Primitive cookie store that stores cookies in a (volatile) hash map.
|
||||
* Will be sufficient for session cookies.
|
||||
*/
|
||||
public class MemoryCookieStore implements CookieJar {
|
||||
|
||||
public static final MemoryCookieStore INSTANCE = new MemoryCookieStore();
|
||||
|
||||
protected final Map<HttpUrl, List<Cookie>> store = new ConcurrentHashMap<>();
|
||||
|
||||
|
||||
@Override
|
||||
public void saveFromResponse(HttpUrl url, List<Cookie> cookies) {
|
||||
store.put(url, cookies);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Cookie> loadForRequest(HttpUrl url) {
|
||||
return store.get(url);
|
||||
}
|
||||
|
||||
}
|
@ -10,7 +10,7 @@ package at.bitfire.davdroid.resource;
|
||||
import android.content.Context;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import com.squareup.okhttp.HttpUrl;
|
||||
import okhttp3.HttpUrl;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.xbill.DNS.Lookup;
|
||||
@ -48,6 +48,7 @@ import at.bitfire.davdroid.ui.setup.LoginCredentialsFragment;
|
||||
import lombok.Data;
|
||||
import lombok.NonNull;
|
||||
import lombok.ToString;
|
||||
import okhttp3.OkHttpClient;
|
||||
|
||||
public class DavResourceFinder {
|
||||
protected enum Service {
|
||||
@ -59,11 +60,12 @@ public class DavResourceFinder {
|
||||
@Override public String toString() { return name; }
|
||||
};
|
||||
|
||||
protected final Logger log;
|
||||
protected final Context context;
|
||||
protected final HttpClient httpClient;
|
||||
protected final LoginCredentialsFragment.LoginCredentials credentials;
|
||||
|
||||
protected final Logger log = new StringLogger("DavResourceFinder", true);
|
||||
protected OkHttpClient httpClient;
|
||||
|
||||
protected HttpUrl carddavPrincipal, caldavPrincipal;
|
||||
protected Map<HttpUrl, ServerConfiguration.Collection>
|
||||
addressBooks = new HashMap<>(),
|
||||
@ -74,8 +76,9 @@ public class DavResourceFinder {
|
||||
this.context = context;
|
||||
this.credentials = credentials;
|
||||
|
||||
log = new StringLogger("DavResourceFinder", true);
|
||||
httpClient = new HttpClient(log, context, credentials.getUserName(), credentials.getPassword(), credentials.isAuthPreemptive());
|
||||
httpClient = HttpClient.create(context);
|
||||
httpClient = HttpClient.addLogger(httpClient, log);
|
||||
httpClient = HttpClient.addAuthentication(httpClient, credentials.getUserName(), credentials.getPassword(), credentials.isAuthPreemptive());
|
||||
}
|
||||
|
||||
|
||||
|
@ -16,10 +16,10 @@ import android.os.Bundle;
|
||||
import android.provider.CalendarContract.Calendars;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import com.squareup.okhttp.HttpUrl;
|
||||
import com.squareup.okhttp.MediaType;
|
||||
import com.squareup.okhttp.RequestBody;
|
||||
import com.squareup.okhttp.ResponseBody;
|
||||
import okhttp3.HttpUrl;
|
||||
import okhttp3.MediaType;
|
||||
import okhttp3.RequestBody;
|
||||
import okhttp3.ResponseBody;
|
||||
|
||||
import org.apache.commons.codec.Charsets;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
@ -14,12 +14,13 @@ import android.content.Context;
|
||||
import android.content.SyncResult;
|
||||
import android.os.Bundle;
|
||||
|
||||
import com.squareup.okhttp.HttpUrl;
|
||||
import com.squareup.okhttp.MediaType;
|
||||
import com.squareup.okhttp.Request;
|
||||
import com.squareup.okhttp.RequestBody;
|
||||
import com.squareup.okhttp.Response;
|
||||
import com.squareup.okhttp.ResponseBody;
|
||||
import okhttp3.HttpUrl;
|
||||
import okhttp3.MediaType;
|
||||
import okhttp3.OkHttpClient;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.RequestBody;
|
||||
import okhttp3.Response;
|
||||
import okhttp3.ResponseBody;
|
||||
|
||||
import org.apache.commons.codec.Charsets;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
@ -144,7 +145,7 @@ public class ContactsSyncManager extends SyncManager {
|
||||
log.info("Downloading " + toDownload.size() + " contacts (" + MAX_MULTIGET + " at once)");
|
||||
|
||||
// prepare downloader which may be used to download external resource like contact photos
|
||||
Contact.Downloader downloader = new ResourceDownloader(httpClient, collectionURL);
|
||||
Contact.Downloader downloader = new ResourceDownloader(collectionURL);
|
||||
|
||||
// download new/updated VCards from server
|
||||
for (DavResource[] bunch : ArrayUtils.partition(toDownload.toArray(new DavResource[toDownload.size()]), MAX_MULTIGET)) {
|
||||
@ -258,7 +259,6 @@ public class ContactsSyncManager extends SyncManager {
|
||||
|
||||
@RequiredArgsConstructor
|
||||
private class ResourceDownloader implements Contact.Downloader {
|
||||
final HttpClient httpClient;
|
||||
final HttpUrl baseUrl;
|
||||
|
||||
@Override
|
||||
@ -276,7 +276,16 @@ public class ContactsSyncManager extends SyncManager {
|
||||
return null;
|
||||
}
|
||||
|
||||
HttpClient resourceClient = new HttpClient(log, httpClient, host);
|
||||
OkHttpClient resourceClient = HttpClient.create(context);
|
||||
|
||||
// authenticate only against a certain host, and only upon request
|
||||
resourceClient = HttpClient.addAuthentication(resourceClient, baseUrl.host(), settings.username(), settings.password(), false);
|
||||
|
||||
// allow redirects
|
||||
resourceClient = resourceClient.newBuilder()
|
||||
.followRedirects(true)
|
||||
.build();
|
||||
|
||||
try {
|
||||
Response response = resourceClient.newCall(new Request.Builder()
|
||||
.get()
|
||||
|
@ -20,8 +20,9 @@ package at.bitfire.davdroid.syncadapter;
|
||||
import android.os.Bundle;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import com.squareup.okhttp.HttpUrl;
|
||||
import com.squareup.okhttp.RequestBody;
|
||||
import okhttp3.HttpUrl;
|
||||
import okhttp3.OkHttpClient;
|
||||
import okhttp3.RequestBody;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
|
||||
@ -81,7 +82,7 @@ abstract public class SyncManager {
|
||||
|
||||
protected Logger log;
|
||||
|
||||
protected final HttpClient httpClient;
|
||||
protected OkHttpClient httpClient;
|
||||
protected HttpUrl collectionURL;
|
||||
protected DavResource davCollection;
|
||||
|
||||
@ -122,7 +123,9 @@ abstract public class SyncManager {
|
||||
log = Constants.log;
|
||||
|
||||
// create HttpClient with given logger
|
||||
httpClient = new HttpClient(log, context, settings.username(), settings.password(), settings.preemptiveAuth());
|
||||
httpClient = HttpClient.create(context);
|
||||
httpClient = HttpClient.addLogger(httpClient, log);
|
||||
httpClient = HttpClient.addAuthentication(httpClient, settings.username(), settings.password(), settings.preemptiveAuth());
|
||||
|
||||
// dismiss previous error notifications
|
||||
notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
|
@ -15,10 +15,10 @@ import android.content.SyncResult;
|
||||
import android.os.Bundle;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import com.squareup.okhttp.HttpUrl;
|
||||
import com.squareup.okhttp.MediaType;
|
||||
import com.squareup.okhttp.RequestBody;
|
||||
import com.squareup.okhttp.ResponseBody;
|
||||
import okhttp3.HttpUrl;
|
||||
import okhttp3.MediaType;
|
||||
import okhttp3.RequestBody;
|
||||
import okhttp3.ResponseBody;
|
||||
|
||||
import org.apache.commons.codec.Charsets;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit c67d40c47e792af812866289b6809dc8ccf49fd8
|
||||
Subproject commit 94a5ee4aec98a29fe1c56046f9a6c71131db8b51
|
Loading…
Reference in New Issue
Block a user