mirror of
https://github.com/square/okhttp.git
synced 2026-01-12 10:23:16 +03:00
Support querying & setting transport lists on connections.
The list is specified via a magic request property "X-Android-Transports" and can be queried via the request property "X-Android-Selected-Transport". System wide defaults / switches don't need any changes to okhttp. They can be set as options on the OkHttpClient used by the platform UrlStreamHandlers.
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -15,6 +15,8 @@ release.properties
|
||||
|
||||
.idea
|
||||
*.iml
|
||||
*.ipr
|
||||
*.iws
|
||||
classes
|
||||
|
||||
obj
|
||||
|
||||
@@ -278,7 +278,7 @@ public class HttpEngine {
|
||||
hostnameVerifier = policy.hostnameVerifier;
|
||||
}
|
||||
Address address = new Address(uriHost, getEffectivePort(uri), sslSocketFactory,
|
||||
hostnameVerifier, policy.authenticator, policy.requestedProxy, policy.transports);
|
||||
hostnameVerifier, policy.authenticator, policy.requestedProxy, policy.getTransports());
|
||||
routeSelector = new RouteSelector(address, uri, policy.proxySelector, policy.connectionPool,
|
||||
Dns.DEFAULT, policy.getFailedRoutes());
|
||||
}
|
||||
|
||||
@@ -127,10 +127,13 @@ public final class HttpTransport implements Transport {
|
||||
}
|
||||
|
||||
@Override public ResponseHeaders readResponseHeaders() throws IOException {
|
||||
RawHeaders headers = RawHeaders.fromBytes(socketIn);
|
||||
httpEngine.connection.setHttpMinorVersion(headers.getHttpMinorVersion());
|
||||
httpEngine.receiveHeaders(headers);
|
||||
return new ResponseHeaders(httpEngine.uri, headers);
|
||||
RawHeaders rawHeaders = RawHeaders.fromBytes(socketIn);
|
||||
httpEngine.connection.setHttpMinorVersion(rawHeaders.getHttpMinorVersion());
|
||||
httpEngine.receiveHeaders(rawHeaders);
|
||||
|
||||
ResponseHeaders headers = new ResponseHeaders(httpEngine.uri, rawHeaders);
|
||||
headers.setTransport("http/1.1");
|
||||
return headers;
|
||||
}
|
||||
|
||||
public boolean makeReusable(boolean streamCancelled, OutputStream requestBodyOut,
|
||||
|
||||
@@ -40,6 +40,7 @@ import java.net.SocketPermission;
|
||||
import java.net.URL;
|
||||
import java.security.Permission;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
@@ -93,7 +94,7 @@ public class HttpURLConnectionImpl extends HttpURLConnection {
|
||||
/* SSL configuration; necessary for HTTP requests that get redirected to HTTPS. */
|
||||
SSLSocketFactory sslSocketFactory;
|
||||
HostnameVerifier hostnameVerifier;
|
||||
List<String> transports;
|
||||
private List<String> transports;
|
||||
OkAuthenticator authenticator;
|
||||
final Set<Route> failedRoutes;
|
||||
|
||||
@@ -125,6 +126,10 @@ public class HttpURLConnectionImpl extends HttpURLConnection {
|
||||
return failedRoutes;
|
||||
}
|
||||
|
||||
List<String> getTransports() {
|
||||
return transports;
|
||||
}
|
||||
|
||||
@Override public final void connect() throws IOException {
|
||||
initHttpEngine();
|
||||
boolean success;
|
||||
@@ -547,7 +552,11 @@ public class HttpURLConnectionImpl extends HttpURLConnection {
|
||||
if (field == null) {
|
||||
throw new NullPointerException("field == null");
|
||||
}
|
||||
rawRequestHeaders.set(field, newValue);
|
||||
if ("X-Android-Transports".equals(field)) {
|
||||
setTransports(newValue, false /* append */);
|
||||
} else {
|
||||
rawRequestHeaders.set(field, newValue);
|
||||
}
|
||||
}
|
||||
|
||||
@Override public final void addRequestProperty(String field, String value) {
|
||||
@@ -557,6 +566,54 @@ public class HttpURLConnectionImpl extends HttpURLConnection {
|
||||
if (field == null) {
|
||||
throw new NullPointerException("field == null");
|
||||
}
|
||||
rawRequestHeaders.add(field, value);
|
||||
|
||||
if ("X-Android-Transports".equals(field)) {
|
||||
setTransports(value, true /* append */);
|
||||
} else {
|
||||
rawRequestHeaders.add(field, value);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Splits and validates a comma-separated string of transports.
|
||||
* When append == false, we require that the transport list contains "http/1.1".
|
||||
*/
|
||||
private void setTransports(String transportsString, boolean append) {
|
||||
if (transportsString == null) {
|
||||
throw new NullPointerException("transportsString == null");
|
||||
}
|
||||
|
||||
String[] transports = transportsString.split(",", -1);
|
||||
ArrayList<String> transportsList = new ArrayList<String>();
|
||||
if (!append) {
|
||||
// If we're not appending to the list, we need to make sure
|
||||
// the list contains "http/1.1". We do this in a separate loop
|
||||
// to avoid modifying any state before we validate the input.
|
||||
boolean containsHttp = false;
|
||||
for (int i = 0; i < transports.length; ++i) {
|
||||
if ("http/1.1".equals(transports[i])) {
|
||||
containsHttp = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!containsHttp) {
|
||||
throw new IllegalArgumentException("Transport list doesn't contain http/1.1");
|
||||
}
|
||||
} else {
|
||||
transportsList.addAll(this.transports);
|
||||
}
|
||||
|
||||
for (int i = 0; i < transports.length; ++i) {
|
||||
if (transports[i].length() == 0) {
|
||||
throw new IllegalArgumentException("Transport list contains an empty transport");
|
||||
}
|
||||
|
||||
if (!transportsList.contains(transports[i])) {
|
||||
transportsList.add(transports[i]);
|
||||
}
|
||||
}
|
||||
|
||||
this.transports = Util.immutableList(transportsList);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,6 +42,9 @@ public final class ResponseHeaders {
|
||||
/** HTTP synthetic header with the response source. */
|
||||
static final String RESPONSE_SOURCE = "X-Android-Response-Source";
|
||||
|
||||
/** HTTP synthetic header with the selected transport (spdy/3, http/1.1, etc.) */
|
||||
static final String SELECTED_TRANSPORT = "X-Android-Selected-Transport";
|
||||
|
||||
private final URI uri;
|
||||
private final RawHeaders headers;
|
||||
|
||||
@@ -278,6 +281,10 @@ public final class ResponseHeaders {
|
||||
headers.set(RESPONSE_SOURCE, responseSource.toString() + " " + headers.getResponseCode());
|
||||
}
|
||||
|
||||
public void setTransport(String transport) {
|
||||
headers.set(SELECTED_TRANSPORT, transport);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current age of the response, in milliseconds. The calculation
|
||||
* is specified by RFC 2616, 13.2.3 Age Calculations.
|
||||
|
||||
@@ -71,7 +71,10 @@ public final class SpdyTransport implements Transport {
|
||||
RawHeaders rawHeaders = RawHeaders.fromNameValueBlock(nameValueBlock);
|
||||
rawHeaders.computeResponseStatusLineFromSpdyHeaders();
|
||||
httpEngine.receiveHeaders(rawHeaders);
|
||||
return new ResponseHeaders(httpEngine.uri, rawHeaders);
|
||||
|
||||
ResponseHeaders headers = new ResponseHeaders(httpEngine.uri, rawHeaders);
|
||||
headers.setTransport("spdy/3");
|
||||
return headers;
|
||||
}
|
||||
|
||||
@Override public InputStream getTransferStream(CacheRequest cacheRequest) throws IOException {
|
||||
|
||||
Reference in New Issue
Block a user