mirror of
https://github.com/square/okhttp.git
synced 2026-01-24 04:02:07 +03:00
Merge pull request #438 from adriancole/consolidate-protocol
consolidate protocol constants
This commit is contained in:
@@ -17,6 +17,7 @@
|
||||
package com.squareup.okhttp.internal.spdy;
|
||||
|
||||
import com.squareup.okhttp.internal.ByteString;
|
||||
import com.squareup.okhttp.Protocol;
|
||||
import com.squareup.okhttp.internal.SslContextBuilder;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
@@ -71,7 +72,7 @@ public final class SpdyServer implements IncomingStreamHandler {
|
||||
System.out.println("UNSUPPORTED");
|
||||
}
|
||||
@Override public List<String> protocols() {
|
||||
return Arrays.asList("spdy/3");
|
||||
return Arrays.asList(Protocol.SPDY_3.name.utf8());
|
||||
}
|
||||
@Override public void protocolSelected(String protocol) {
|
||||
System.out.println("PROTOCOL SELECTED: " + protocol);
|
||||
|
||||
@@ -20,6 +20,7 @@ package com.squareup.okhttp.mockwebserver;
|
||||
import com.squareup.okhttp.internal.ByteString;
|
||||
import com.squareup.okhttp.internal.NamedRunnable;
|
||||
import com.squareup.okhttp.internal.Platform;
|
||||
import com.squareup.okhttp.Protocol;
|
||||
import com.squareup.okhttp.internal.Util;
|
||||
import com.squareup.okhttp.internal.spdy.IncomingStreamHandler;
|
||||
import com.squareup.okhttp.internal.spdy.SpdyConnection;
|
||||
@@ -43,7 +44,6 @@ import java.security.SecureRandom;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
@@ -71,29 +71,6 @@ import static com.squareup.okhttp.mockwebserver.SocketPolicy.FAIL_HANDSHAKE;
|
||||
* replays them upon request in sequence.
|
||||
*/
|
||||
public final class MockWebServer {
|
||||
private static final byte[] HTTP_20_DRAFT_09 = new byte[] {
|
||||
'H', 'T', 'T', 'P', '-', 'd', 'r', 'a', 'f', 't', '-', '0', '9', '/', '2', '.', '0'
|
||||
};
|
||||
private static final byte[] SPDY3 = new byte[] {
|
||||
's', 'p', 'd', 'y', '/', '3'
|
||||
};
|
||||
private static final byte[] HTTP_11 = new byte[] {
|
||||
'h', 't', 't', 'p', '/', '1', '.', '1'
|
||||
};
|
||||
private static final byte[] NPN_PROTOCOLS = joinNpnProtocols(HTTP_20_DRAFT_09, SPDY3, HTTP_11);
|
||||
|
||||
private static byte[] joinNpnProtocols(byte[]... protocols) {
|
||||
try {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
for (byte[] protocol : protocols) {
|
||||
baos.write(protocol.length);
|
||||
baos.write(protocol);
|
||||
}
|
||||
return baos.toByteArray();
|
||||
} catch (IOException e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
}
|
||||
|
||||
private static final X509TrustManager UNTRUSTED_TRUST_MANAGER = new X509TrustManager() {
|
||||
@Override public void checkClientTrusted(X509Certificate[] chain, String authType)
|
||||
@@ -181,7 +158,7 @@ public final class MockWebServer {
|
||||
|
||||
/**
|
||||
* Sets whether NPN is used on incoming HTTPS connections to negotiate a
|
||||
* transport like HTTP/1.1 or SPDY/3. Call this method to disable NPN and
|
||||
* protocol like HTTP/1.1 or SPDY/3. Call this method to disable NPN and
|
||||
* SPDY.
|
||||
*/
|
||||
public void setNpnEnabled(boolean npnEnabled) {
|
||||
@@ -308,7 +285,7 @@ public final class MockWebServer {
|
||||
}
|
||||
|
||||
public void processConnection() throws Exception {
|
||||
Transport transport = Transport.HTTP_11;
|
||||
Protocol protocol = Protocol.HTTP_11;
|
||||
Socket socket;
|
||||
if (sslSocketFactory != null) {
|
||||
if (tunnelProxy) {
|
||||
@@ -327,39 +304,26 @@ public final class MockWebServer {
|
||||
openClientSockets.put(socket, true);
|
||||
|
||||
if (npnEnabled) {
|
||||
Platform.get().setNpnProtocols(sslSocket, NPN_PROTOCOLS);
|
||||
// TODO: expose means to select which protocols to advertise.
|
||||
Platform.get().setNpnProtocols(sslSocket, Protocol.HTTP2_SPDY3_AND_HTTP);
|
||||
}
|
||||
|
||||
sslSocket.startHandshake();
|
||||
|
||||
if (npnEnabled) {
|
||||
byte[] selectedProtocol = Platform.get().getNpnSelectedProtocol(sslSocket);
|
||||
if (selectedProtocol == null || Arrays.equals(selectedProtocol, HTTP_11)) {
|
||||
transport = Transport.HTTP_11;
|
||||
} else if (Arrays.equals(selectedProtocol, HTTP_20_DRAFT_09)) {
|
||||
transport = Transport.HTTP_20_DRAFT_09;
|
||||
} else if (Arrays.equals(selectedProtocol, SPDY3)) {
|
||||
transport = Transport.SPDY_3;
|
||||
} else {
|
||||
throw new IllegalStateException(
|
||||
"Unexpected transport: " + new String(selectedProtocol, Util.US_ASCII));
|
||||
}
|
||||
ByteString selectedProtocol = Platform.get().getNpnSelectedProtocol(sslSocket);
|
||||
protocol = Protocol.find(selectedProtocol);
|
||||
}
|
||||
openClientSockets.remove(raw);
|
||||
} else {
|
||||
socket = raw;
|
||||
}
|
||||
|
||||
if (transport == Transport.HTTP_20_DRAFT_09 || transport == Transport.SPDY_3) {
|
||||
SpdySocketHandler spdySocketHandler = new SpdySocketHandler(socket, transport);
|
||||
SpdyConnection.Builder builder = new SpdyConnection.Builder(false, socket)
|
||||
.handler(spdySocketHandler);
|
||||
if (transport == Transport.HTTP_20_DRAFT_09) {
|
||||
builder.http20Draft09();
|
||||
} else {
|
||||
builder.spdy3();
|
||||
}
|
||||
SpdyConnection spdyConnection = builder.build();
|
||||
if (protocol.spdyVariant) {
|
||||
SpdySocketHandler spdySocketHandler = new SpdySocketHandler(socket, protocol);
|
||||
SpdyConnection spdyConnection = new SpdyConnection.Builder(false, socket)
|
||||
.protocol(protocol)
|
||||
.handler(spdySocketHandler).build();
|
||||
openSpdyConnections.put(spdyConnection, Boolean.TRUE);
|
||||
openClientSockets.remove(socket);
|
||||
spdyConnection.readConnectionHeader();
|
||||
@@ -628,12 +592,12 @@ public final class MockWebServer {
|
||||
/** Processes HTTP requests layered over SPDY/3. */
|
||||
private class SpdySocketHandler implements IncomingStreamHandler {
|
||||
private final Socket socket;
|
||||
private final Transport transport;
|
||||
private final Protocol protocol;
|
||||
private final AtomicInteger sequenceNumber = new AtomicInteger();
|
||||
|
||||
private SpdySocketHandler(Socket socket, Transport transport) {
|
||||
private SpdySocketHandler(Socket socket, Protocol protocol) {
|
||||
this.socket = socket;
|
||||
this.transport = transport;
|
||||
this.protocol = protocol;
|
||||
}
|
||||
|
||||
@Override public void receive(SpdyStream stream) throws IOException {
|
||||
@@ -647,7 +611,7 @@ public final class MockWebServer {
|
||||
}
|
||||
writeResponse(stream, response);
|
||||
logger.info("Received request: " + request + " and responded: " + response
|
||||
+ " transport is " + transport);
|
||||
+ " protocol is " + protocol.name.utf8());
|
||||
}
|
||||
|
||||
private RecordedRequest readRequest(SpdyStream stream) throws IOException {
|
||||
@@ -724,8 +688,4 @@ public final class MockWebServer {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum Transport {
|
||||
HTTP_11, SPDY_3, HTTP_20_DRAFT_09
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Copyright (C) 2014 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.
|
||||
*/
|
||||
package com.squareup.okhttp;
|
||||
|
||||
import com.squareup.okhttp.internal.ByteString;
|
||||
import com.squareup.okhttp.internal.Util;
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Contains protocols that OkHttp supports
|
||||
* <a href="http://tools.ietf.org/html/draft-agl-tls-nextprotoneg-04">NPN</a> or
|
||||
* <a href="http://tools.ietf.org/html/draft-ietf-tls-applayerprotoneg">ALPN</a> selection.
|
||||
*
|
||||
* <p/>
|
||||
* <h3>Protocol vs Scheme</h3>
|
||||
* Despite its name, {@link java.net.URL#getProtocol()} returns the
|
||||
* {@link java.net.URI#getScheme() scheme} (http, https, etc.) of the URL, not
|
||||
* the protocol (http/1.1, spdy/3, etc.). OkHttp uses the word protocol to
|
||||
* indicate how HTTP messages are framed.
|
||||
*/
|
||||
public enum Protocol {
|
||||
HTTP_2("HTTP-draft-09/2.0", true),
|
||||
SPDY_3("spdy/3", true),
|
||||
HTTP_11("http/1.1", false);
|
||||
|
||||
public static final List<Protocol> HTTP2_SPDY3_AND_HTTP =
|
||||
Util.immutableList(Arrays.asList(HTTP_2, SPDY_3, HTTP_11));
|
||||
public static final List<Protocol> SPDY3_AND_HTTP11 =
|
||||
Util.immutableList(Arrays.asList(SPDY_3, HTTP_11));
|
||||
public static final List<Protocol> HTTP2_AND_HTTP_11 =
|
||||
Util.immutableList(Arrays.asList(HTTP_2, HTTP_11));
|
||||
|
||||
/** Identifier string used in NPN or ALPN selection. */
|
||||
public final ByteString name;
|
||||
|
||||
/**
|
||||
* When true the protocol is binary framed and derived from SPDY.
|
||||
*
|
||||
* @see com.squareup.okhttp.internal.spdy.Variant
|
||||
*/
|
||||
public final boolean spdyVariant;
|
||||
|
||||
Protocol(String name, boolean spdyVariant) {
|
||||
this.name = ByteString.encodeUtf8(name);
|
||||
this.spdyVariant = spdyVariant;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the protocol matching {@code input} or {@link #HTTP_11} is on
|
||||
* {@code null}. Throws an {@link IOException} when {@code input} doesn't
|
||||
* match the {@link #name} of a supported protocol.
|
||||
*/
|
||||
public static Protocol find(ByteString input) throws IOException {
|
||||
if (input == null) return HTTP_11;
|
||||
for (Protocol protocol : values()) {
|
||||
if (protocol.name.equals(input)) return protocol;
|
||||
}
|
||||
throw new IOException("Unexpected protocol: " + input.utf8());
|
||||
}
|
||||
}
|
||||
@@ -115,7 +115,7 @@ public final class ByteString {
|
||||
System.arraycopy(byteString.data, 0, result, pos, byteString.size());
|
||||
pos += byteString.size();
|
||||
}
|
||||
return ByteString.of(result);
|
||||
return new ByteString(result);
|
||||
}
|
||||
|
||||
private ByteString(byte[] data) {
|
||||
@@ -141,11 +141,6 @@ public final class ByteString {
|
||||
out.write(data);
|
||||
}
|
||||
|
||||
/** Writes a subsequence of this byte string to {@code out}. */
|
||||
public void write(OutputStream out, int offset, int count) throws IOException {
|
||||
out.write(data, offset, count);
|
||||
}
|
||||
|
||||
@Override public boolean equals(Object o) {
|
||||
return o == this || o instanceof ByteString && Arrays.equals(((ByteString) o).data, data);
|
||||
}
|
||||
|
||||
@@ -16,9 +16,9 @@
|
||||
*/
|
||||
package com.squareup.okhttp.internal;
|
||||
|
||||
import com.squareup.okhttp.Protocol;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.InvocationHandler;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
@@ -106,7 +106,7 @@ public class Platform {
|
||||
}
|
||||
|
||||
/** Returns the negotiated protocol, or null if no protocol was negotiated. */
|
||||
public byte[] getNpnSelectedProtocol(SSLSocket socket) {
|
||||
public ByteString getNpnSelectedProtocol(SSLSocket socket) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -114,7 +114,7 @@ public class Platform {
|
||||
* Sets client-supported protocols on a socket to send to a server. The
|
||||
* protocols are only sent if the socket implementation supports NPN.
|
||||
*/
|
||||
public void setNpnProtocols(SSLSocket socket, byte[] npnProtocols) {
|
||||
public void setNpnProtocols(SSLSocket socket, List<Protocol> npnProtocols) {
|
||||
}
|
||||
|
||||
public void connectSocket(Socket socket, InetSocketAddress address,
|
||||
@@ -267,11 +267,11 @@ public class Platform {
|
||||
}
|
||||
}
|
||||
|
||||
@Override public void setNpnProtocols(SSLSocket socket, byte[] npnProtocols) {
|
||||
@Override public void setNpnProtocols(SSLSocket socket, List<Protocol> npnProtocols) {
|
||||
if (setNpnProtocols == null) return;
|
||||
if (!openSslSocketClass.isInstance(socket)) return;
|
||||
try {
|
||||
Object[] parameters = { npnProtocols };
|
||||
Object[] parameters = { concatLengthPrefixed(npnProtocols) };
|
||||
if (setAlpnProtocols != null) {
|
||||
setAlpnProtocols.invoke(socket, parameters);
|
||||
}
|
||||
@@ -283,16 +283,16 @@ public class Platform {
|
||||
}
|
||||
}
|
||||
|
||||
@Override public byte[] getNpnSelectedProtocol(SSLSocket socket) {
|
||||
@Override public ByteString getNpnSelectedProtocol(SSLSocket socket) {
|
||||
if (getNpnSelectedProtocol == null) return null;
|
||||
if (!openSslSocketClass.isInstance(socket)) return null;
|
||||
try {
|
||||
if (getAlpnSelectedProtocol != null) {
|
||||
// Prefer ALPN's result if it is present.
|
||||
byte[] alpnResult = (byte[]) getAlpnSelectedProtocol.invoke(socket);
|
||||
if (alpnResult != null) return alpnResult;
|
||||
if (alpnResult != null) return ByteString.of(alpnResult);
|
||||
}
|
||||
return (byte[]) getNpnSelectedProtocol.invoke(socket);
|
||||
return ByteString.of((byte[]) getNpnSelectedProtocol.invoke(socket));
|
||||
} catch (InvocationTargetException e) {
|
||||
throw new RuntimeException(e);
|
||||
} catch (IllegalAccessException e) {
|
||||
@@ -316,20 +316,15 @@ public class Platform {
|
||||
this.serverProviderClass = serverProviderClass;
|
||||
}
|
||||
|
||||
@Override public void setNpnProtocols(SSLSocket socket, byte[] npnProtocols) {
|
||||
@Override public void setNpnProtocols(SSLSocket socket, List<Protocol> npnProtocols) {
|
||||
try {
|
||||
List<String> strings = new ArrayList<String>();
|
||||
for (int i = 0; i < npnProtocols.length; ) {
|
||||
int length = npnProtocols[i++];
|
||||
strings.add(new String(npnProtocols, i, length, "US-ASCII"));
|
||||
i += length;
|
||||
List<String> names = new ArrayList<String>(npnProtocols.size());
|
||||
for (int i = 0, size = npnProtocols.size(); i < size; i++) {
|
||||
names.add(npnProtocols.get(i).name.utf8());
|
||||
}
|
||||
Object provider = Proxy.newProxyInstance(Platform.class.getClassLoader(),
|
||||
new Class[] {clientProviderClass, serverProviderClass},
|
||||
new JettyNpnProvider(strings));
|
||||
new Class[] { clientProviderClass, serverProviderClass }, new JettyNpnProvider(names));
|
||||
putMethod.invoke(null, socket, provider);
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
throw new AssertionError(e);
|
||||
} catch (InvocationTargetException e) {
|
||||
throw new AssertionError(e);
|
||||
} catch (IllegalAccessException e) {
|
||||
@@ -337,7 +332,7 @@ public class Platform {
|
||||
}
|
||||
}
|
||||
|
||||
@Override public byte[] getNpnSelectedProtocol(SSLSocket socket) {
|
||||
@Override public ByteString getNpnSelectedProtocol(SSLSocket socket) {
|
||||
try {
|
||||
JettyNpnProvider provider =
|
||||
(JettyNpnProvider) Proxy.getInvocationHandler(getMethod.invoke(null, socket));
|
||||
@@ -347,9 +342,7 @@ public class Platform {
|
||||
"NPN callback dropped so SPDY is disabled. " + "Is npn-boot on the boot class path?");
|
||||
return null;
|
||||
}
|
||||
return provider.unsupported ? null : provider.selected.getBytes("US-ASCII");
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
throw new AssertionError();
|
||||
return provider.unsupported ? null : ByteString.encodeUtf8(provider.selected);
|
||||
} catch (InvocationTargetException e) {
|
||||
throw new AssertionError();
|
||||
} catch (IllegalAccessException e) {
|
||||
@@ -400,4 +393,26 @@ public class Platform {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Concatenation of 8-bit, length prefixed protocol names.
|
||||
*
|
||||
* http://tools.ietf.org/html/draft-agl-tls-nextprotoneg-04#page-4
|
||||
*/
|
||||
static byte[] concatLengthPrefixed(List<Protocol> protocols) {
|
||||
int size = 0;
|
||||
for (Protocol protocol : protocols) {
|
||||
size += protocol.name.size() + 1; // add a byte for 8-bit length prefix.
|
||||
}
|
||||
byte[] result = new byte[size];
|
||||
int pos = 0;
|
||||
for (Protocol protocol : protocols) {
|
||||
int nameSize = protocol.name.size();
|
||||
result[pos++] = (byte) nameSize;
|
||||
// toByteArray allocates an array, but this is only called on new connections.
|
||||
System.arraycopy(protocol.name.toByteArray(), 0, result, pos, nameSize);
|
||||
pos += nameSize;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -400,11 +400,19 @@ public final class Util {
|
||||
};
|
||||
}
|
||||
|
||||
public static List<ByteString> byteStringList(String... strings) {
|
||||
List<ByteString> result = new ArrayList<ByteString>(strings.length);
|
||||
for (String string : strings) {
|
||||
public static List<ByteString> byteStringList(String... elements) {
|
||||
List<ByteString> result = new ArrayList<ByteString>(elements.length);
|
||||
for (String string : elements) {
|
||||
result.add(ByteString.encodeUtf8(string));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static List<ByteString> byteStringList(List<String> elements) {
|
||||
List<ByteString> result = new ArrayList<ByteString>(elements.size());
|
||||
for (int i = 0, size = elements.size(); i < size; i++) {
|
||||
result.add(ByteString.encodeUtf8(elements.get(i)));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -405,6 +405,7 @@ final class HpackDraft05 {
|
||||
}
|
||||
}
|
||||
|
||||
// http://tools.ietf.org/html/draft-ietf-httpbis-header-compression-05#section-4.1.1
|
||||
public void writeInt(int value, int prefixMask, int bits) throws IOException {
|
||||
// Write the raw value for a single byte value.
|
||||
if (value < prefixMask) {
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
package com.squareup.okhttp.internal.spdy;
|
||||
|
||||
import com.squareup.okhttp.internal.ByteString;
|
||||
import com.squareup.okhttp.Protocol;
|
||||
import com.squareup.okhttp.internal.Util;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.DataInputStream;
|
||||
@@ -33,8 +34,8 @@ import java.util.List;
|
||||
*/
|
||||
public final class Http20Draft09 implements Variant {
|
||||
|
||||
@Override public String getProtocol() {
|
||||
return "HTTP-draft-09/2.0";
|
||||
@Override public Protocol getProtocol() {
|
||||
return Protocol.HTTP_2;
|
||||
}
|
||||
|
||||
private static final byte[] CONNECTION_HEADER;
|
||||
|
||||
@@ -17,6 +17,7 @@ package com.squareup.okhttp.internal.spdy;
|
||||
|
||||
import com.squareup.okhttp.internal.ByteString;
|
||||
import com.squareup.okhttp.internal.Platform;
|
||||
import com.squareup.okhttp.Protocol;
|
||||
import com.squareup.okhttp.internal.Util;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.DataInputStream;
|
||||
@@ -31,8 +32,8 @@ import java.util.zip.Deflater;
|
||||
|
||||
final class Spdy3 implements Variant {
|
||||
|
||||
@Override public String getProtocol() {
|
||||
return "spdy/3";
|
||||
@Override public Protocol getProtocol() {
|
||||
return Protocol.SPDY_3;
|
||||
}
|
||||
|
||||
static final int TYPE_DATA = 0x0;
|
||||
|
||||
@@ -18,6 +18,7 @@ package com.squareup.okhttp.internal.spdy;
|
||||
|
||||
import com.squareup.okhttp.internal.ByteString;
|
||||
import com.squareup.okhttp.internal.NamedRunnable;
|
||||
import com.squareup.okhttp.Protocol;
|
||||
import com.squareup.okhttp.internal.Util;
|
||||
import java.io.Closeable;
|
||||
import java.io.IOException;
|
||||
@@ -60,7 +61,7 @@ public final class SpdyConnection implements Closeable {
|
||||
Integer.MAX_VALUE, 60, TimeUnit.SECONDS, new SynchronousQueue<Runnable>(),
|
||||
Util.threadFactory("OkHttp SpdyConnection", true));
|
||||
|
||||
/** The protocol variant, like SPDY/3 or HTTP-draft-09/2.0. */
|
||||
/** The protocol variant, like {@link com.squareup.okhttp.internal.spdy.Spdy3}. */
|
||||
final Variant variant;
|
||||
|
||||
/** True if this peer initiated the connection. */
|
||||
@@ -104,12 +105,8 @@ public final class SpdyConnection implements Closeable {
|
||||
new Thread(new Reader()).start(); // Not a daemon thread.
|
||||
}
|
||||
|
||||
/**
|
||||
* The protocol name, like {@code spdy/3} or {@code HTTP-draft-09/2.0}.
|
||||
*
|
||||
* @see com.squareup.okhttp.internal.spdy.Variant#getProtocol()
|
||||
*/
|
||||
public String getProtocol() {
|
||||
/** The protocol as selected using NPN or ALPN. */
|
||||
public Protocol getProtocol() {
|
||||
return variant.getProtocol();
|
||||
}
|
||||
|
||||
@@ -423,13 +420,15 @@ public final class SpdyConnection implements Closeable {
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder spdy3() {
|
||||
this.variant = Variant.SPDY3;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder http20Draft09() {
|
||||
this.variant = Variant.HTTP_20_DRAFT_09;
|
||||
public Builder protocol(Protocol protocol) {
|
||||
// TODO: protocol == variant.getProtocol, so we could map this.
|
||||
if (protocol == Protocol.HTTP_2) {
|
||||
this.variant = Variant.HTTP_20_DRAFT_09;
|
||||
} else if (protocol == Protocol.SPDY_3) {
|
||||
this.variant = Variant.SPDY3;
|
||||
} else {
|
||||
throw new AssertionError(protocol);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package com.squareup.okhttp.internal.spdy;
|
||||
|
||||
import com.squareup.okhttp.Protocol;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
||||
@@ -23,8 +24,8 @@ interface Variant {
|
||||
Variant SPDY3 = new Spdy3();
|
||||
Variant HTTP_20_DRAFT_09 = new Http20Draft09();
|
||||
|
||||
/** The protocol name, like {@code spdy/3} or {@code HTTP-draft-09/2.0}. */
|
||||
String getProtocol();
|
||||
/** The protocol as selected using NPN or ALPN. */
|
||||
Protocol getProtocol();
|
||||
|
||||
/**
|
||||
* @param client true if this is the HTTP client's reader, reading frames from
|
||||
|
||||
@@ -66,12 +66,6 @@ public class ByteStringTest {
|
||||
assertByteArraysEquals(new byte[] { 0x61, 0x62, 0x63 }, out.toByteArray());
|
||||
}
|
||||
|
||||
@Test public void writeWithOffset() throws Exception {
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
ByteString.of((byte) 0x61, (byte) 0x62, (byte) 0x63).write(out, 1, 2);
|
||||
assertByteArraysEquals(new byte[] { 0x62, 0x63 }, out.toByteArray());
|
||||
}
|
||||
|
||||
@Test public void concat() {
|
||||
assertEquals(ByteString.of(), ByteString.concat());
|
||||
assertEquals(ByteString.of(), ByteString.concat(ByteString.EMPTY));
|
||||
|
||||
@@ -41,22 +41,22 @@ public final class Address {
|
||||
final SSLSocketFactory sslSocketFactory;
|
||||
final HostnameVerifier hostnameVerifier;
|
||||
final OkAuthenticator authenticator;
|
||||
final List<String> transports;
|
||||
final List<Protocol> protocols;
|
||||
|
||||
public Address(String uriHost, int uriPort, SSLSocketFactory sslSocketFactory,
|
||||
HostnameVerifier hostnameVerifier, OkAuthenticator authenticator, Proxy proxy,
|
||||
List<String> transports) throws UnknownHostException {
|
||||
List<Protocol> protocols) throws UnknownHostException {
|
||||
if (uriHost == null) throw new NullPointerException("uriHost == null");
|
||||
if (uriPort <= 0) throw new IllegalArgumentException("uriPort <= 0: " + uriPort);
|
||||
if (authenticator == null) throw new IllegalArgumentException("authenticator == null");
|
||||
if (transports == null) throw new IllegalArgumentException("transports == null");
|
||||
if (protocols == null) throw new IllegalArgumentException("protocols == null");
|
||||
this.proxy = proxy;
|
||||
this.uriHost = uriHost;
|
||||
this.uriPort = uriPort;
|
||||
this.sslSocketFactory = sslSocketFactory;
|
||||
this.hostnameVerifier = hostnameVerifier;
|
||||
this.authenticator = authenticator;
|
||||
this.transports = Util.immutableList(transports);
|
||||
this.protocols = Util.immutableList(protocols);
|
||||
}
|
||||
|
||||
/** Returns the hostname of the origin server. */
|
||||
@@ -97,11 +97,12 @@ public final class Address {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the client's transports. This method always returns a non-null list
|
||||
* that contains "http/1.1", possibly among other transports.
|
||||
* Returns the protocols the client supports. This method always returns a
|
||||
* non-null list that contains minimally
|
||||
* {@link Protocol#HTTP_11}.
|
||||
*/
|
||||
public List<String> getTransports() {
|
||||
return transports;
|
||||
public List<Protocol> getProtocols() {
|
||||
return protocols;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -121,7 +122,7 @@ public final class Address {
|
||||
&& equal(this.sslSocketFactory, that.sslSocketFactory)
|
||||
&& equal(this.hostnameVerifier, that.hostnameVerifier)
|
||||
&& equal(this.authenticator, that.authenticator)
|
||||
&& equal(this.transports, that.transports);
|
||||
&& equal(this.protocols, that.protocols);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -134,7 +135,7 @@ public final class Address {
|
||||
result = 31 * result + (hostnameVerifier != null ? hostnameVerifier.hashCode() : 0);
|
||||
result = 31 * result + (authenticator != null ? authenticator.hashCode() : 0);
|
||||
result = 31 * result + (proxy != null ? proxy.hashCode() : 0);
|
||||
result = 31 * result + transports.hashCode();
|
||||
result = 31 * result + protocols.hashCode();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
*/
|
||||
package com.squareup.okhttp;
|
||||
|
||||
import com.squareup.okhttp.internal.ByteString;
|
||||
import com.squareup.okhttp.internal.Platform;
|
||||
import com.squareup.okhttp.internal.http.HttpAuthenticator;
|
||||
import com.squareup.okhttp.internal.http.HttpEngine;
|
||||
@@ -31,7 +32,6 @@ import java.io.OutputStream;
|
||||
import java.net.Proxy;
|
||||
import java.net.Socket;
|
||||
import java.net.SocketTimeoutException;
|
||||
import java.util.Arrays;
|
||||
import javax.net.ssl.SSLSocket;
|
||||
|
||||
import static java.net.HttpURLConnection.HTTP_OK;
|
||||
@@ -56,7 +56,7 @@ import static java.net.HttpURLConnection.HTTP_PROXY_AUTH;
|
||||
* <li>Server Name Indication (SNI) enables one IP address to negotiate secure
|
||||
* connections for multiple domain names.
|
||||
* <li>Next Protocol Negotiation (NPN) enables the HTTPS port (443) to be used
|
||||
* for both HTTP and SPDY transports.
|
||||
* for both HTTP and SPDY protocols.
|
||||
* </ul>
|
||||
* Unfortunately, older HTTPS servers refuse to connect when such options are
|
||||
* presented. Rather than avoiding these options entirely, this class allows a
|
||||
@@ -64,31 +64,6 @@ import static java.net.HttpURLConnection.HTTP_PROXY_AUTH;
|
||||
* should the attempt fail.
|
||||
*/
|
||||
public final class Connection implements Closeable {
|
||||
private static final byte[] ALL_PROTOCOLS = new byte[] {
|
||||
17, 'H', 'T', 'T', 'P', '-', 'd', 'r', 'a', 'f', 't', '-', '0', '9', '/', '2', '.', '0',
|
||||
6, 's', 'p', 'd', 'y', '/', '3',
|
||||
8, 'h', 't', 't', 'p', '/', '1', '.', '1'
|
||||
};
|
||||
|
||||
private static final byte[] SPDY3_AND_HTTP11 = new byte[] {
|
||||
6, 's', 'p', 'd', 'y', '/', '3',
|
||||
8, 'h', 't', 't', 'p', '/', '1', '.', '1'
|
||||
};
|
||||
|
||||
private static final byte[] HTTP2_AND_HTTP = new byte[] {
|
||||
17, 'H', 'T', 'T', 'P', '-', 'd', 'r', 'a', 'f', 't', '-', '0', '9', '/', '2', '.', '0',
|
||||
8, 'h', 't', 't', 'p', '/', '1', '.', '1'
|
||||
};
|
||||
|
||||
private static final byte[] HTTP_20_DRAFT_09 = new byte[] {
|
||||
'H', 'T', 'T', 'P', '-', 'd', 'r', 'a', 'f', 't', '-', '0', '9', '/', '2', '.', '0'
|
||||
};
|
||||
private static final byte[] SPDY3 = new byte[] {
|
||||
's', 'p', 'd', 'y', '/', '3'
|
||||
};
|
||||
private static final byte[] HTTP_11 = new byte[] {
|
||||
'h', 't', 't', 'p', '/', '1', '.', '1'
|
||||
};
|
||||
|
||||
private final Route route;
|
||||
|
||||
@@ -145,19 +120,19 @@ public final class Connection implements Closeable {
|
||||
platform.supportTlsIntolerantServer(sslSocket);
|
||||
}
|
||||
|
||||
boolean useNpn = route.modernTls && (
|
||||
route.address.transports.contains("HTTP-draft-09/2.0")
|
||||
|| route.address.transports.contains("spdy/3")
|
||||
boolean useNpn = route.modernTls && (// Contains a spdy variant.
|
||||
route.address.protocols.contains(Protocol.HTTP_2)
|
||||
|| route.address.protocols.contains(Protocol.SPDY_3)
|
||||
);
|
||||
|
||||
if (useNpn) {
|
||||
if (route.address.transports.contains("HTTP-draft-09/2.0")
|
||||
&& route.address.transports.contains("spdy/3")) {
|
||||
platform.setNpnProtocols(sslSocket, ALL_PROTOCOLS);
|
||||
} else if (route.address.transports.contains("HTTP-draft-09/2.0")) {
|
||||
platform.setNpnProtocols(sslSocket, HTTP2_AND_HTTP);
|
||||
if (route.address.protocols.contains(Protocol.HTTP_2) // Contains both spdy variants.
|
||||
&& route.address.protocols.contains(Protocol.SPDY_3)) {
|
||||
platform.setNpnProtocols(sslSocket, Protocol.HTTP2_SPDY3_AND_HTTP);
|
||||
} else if (route.address.protocols.contains(Protocol.HTTP_2)) {
|
||||
platform.setNpnProtocols(sslSocket, Protocol.HTTP2_AND_HTTP_11);
|
||||
} else {
|
||||
platform.setNpnProtocols(sslSocket, SPDY3_AND_HTTP11);
|
||||
platform.setNpnProtocols(sslSocket, Protocol.SPDY3_AND_HTTP11);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -174,19 +149,14 @@ public final class Connection implements Closeable {
|
||||
handshake = Handshake.get(sslSocket.getSession());
|
||||
streamWrapper();
|
||||
|
||||
byte[] selectedProtocol;
|
||||
if (useNpn && (selectedProtocol = platform.getNpnSelectedProtocol(sslSocket)) != null) {
|
||||
if (Arrays.equals(selectedProtocol, HTTP_20_DRAFT_09)
|
||||
|| Arrays.equals(selectedProtocol, SPDY3)) {
|
||||
SpdyConnection.Builder builder =
|
||||
new SpdyConnection.Builder(route.address.getUriHost(), true, in, out);
|
||||
if (Arrays.equals(selectedProtocol, HTTP_20_DRAFT_09)) builder.http20Draft09();
|
||||
ByteString maybeProtocol;
|
||||
if (useNpn && (maybeProtocol = platform.getNpnSelectedProtocol(sslSocket)) != null) {
|
||||
Protocol selectedProtocol = Protocol.find(maybeProtocol); // Throws IOE on unknown.
|
||||
if (selectedProtocol.spdyVariant) {
|
||||
sslSocket.setSoTimeout(0); // SPDY timeouts are set per-stream.
|
||||
spdyConnection = builder.build();
|
||||
spdyConnection = new SpdyConnection.Builder(route.address.getUriHost(), true, in, out)
|
||||
.protocol(selectedProtocol).build();
|
||||
spdyConnection.sendConnectionHeader();
|
||||
} else if (!Arrays.equals(selectedProtocol, HTTP_11)) {
|
||||
throw new IOException(
|
||||
"Unexpected NPN transport " + new String(selectedProtocol, "ISO-8859-1"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,11 +15,13 @@
|
||||
*/
|
||||
package com.squareup.okhttp;
|
||||
|
||||
import com.squareup.okhttp.internal.ByteString;
|
||||
import com.squareup.okhttp.internal.Util;
|
||||
import com.squareup.okhttp.internal.http.HttpAuthenticator;
|
||||
import com.squareup.okhttp.internal.http.HttpURLConnectionImpl;
|
||||
import com.squareup.okhttp.internal.http.HttpsURLConnectionImpl;
|
||||
import com.squareup.okhttp.internal.tls.OkHostnameVerifier;
|
||||
import java.io.IOException;
|
||||
import java.net.CookieHandler;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.Proxy;
|
||||
@@ -29,7 +31,7 @@ import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
import java.net.URLStreamHandler;
|
||||
import java.net.URLStreamHandlerFactory;
|
||||
import java.util.Arrays;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import javax.net.ssl.HostnameVerifier;
|
||||
@@ -38,13 +40,11 @@ import javax.net.ssl.SSLSocketFactory;
|
||||
|
||||
/** Configures and creates HTTP connections. */
|
||||
public final class OkHttpClient implements URLStreamHandlerFactory, Cloneable {
|
||||
private static final List<String> DEFAULT_TRANSPORTS
|
||||
= Util.immutableList(Arrays.asList("HTTP-draft-09/2.0", "spdy/3", "http/1.1"));
|
||||
|
||||
private final RouteDatabase routeDatabase;
|
||||
private Dispatcher dispatcher;
|
||||
private Proxy proxy;
|
||||
private List<String> transports;
|
||||
private List<Protocol> protocols;
|
||||
private ProxySelector proxySelector;
|
||||
private CookieHandler cookieHandler;
|
||||
private OkResponseCache responseCache;
|
||||
@@ -296,20 +296,39 @@ public final class OkHttpClient implements URLStreamHandlerFactory, Cloneable {
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure the transports used by this client to communicate with remote
|
||||
* @deprecated OkHttp 2 enforces an enumeration of {@link Protocol protocols}
|
||||
* that can be selected. Please switch to {@link #setProtocols(java.util.List)}.
|
||||
*/
|
||||
@Deprecated
|
||||
public OkHttpClient setTransports(List<String> transports) {
|
||||
List<Protocol> protocols = new ArrayList<Protocol>(transports.size());
|
||||
for (int i = 0, size = transports.size(); i < size; i++) {
|
||||
try {
|
||||
Protocol protocol = Protocol.find(ByteString.encodeUtf8(transports.get(i)));
|
||||
protocols.add(protocol);
|
||||
} catch (IOException e) {
|
||||
throw new IllegalArgumentException(e);
|
||||
}
|
||||
}
|
||||
return setProtocols(protocols);
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure the protocols used by this client to communicate with remote
|
||||
* servers. By default this client will prefer the most efficient transport
|
||||
* available, falling back to more ubiquitous transports. Applications should
|
||||
* available, falling back to more ubiquitous protocols. Applications should
|
||||
* only call this method to avoid specific compatibility problems, such as web
|
||||
* servers that behave incorrectly when SPDY is enabled.
|
||||
*
|
||||
* <p>The following transports are currently supported:
|
||||
* <p>The following protocols are currently supported:
|
||||
* <ul>
|
||||
* <li><a href="http://www.w3.org/Protocols/rfc2616/rfc2616.html">http/1.1</a>
|
||||
* <li><a href="http://www.chromium.org/spdy/spdy-protocol/spdy-protocol-draft3">spdy/3</a>
|
||||
* <li><a href="http://tools.ietf.org/html/draft-ietf-httpbis-http2-09">HTTP-draft-09/2.0</a>
|
||||
* </ul>
|
||||
*
|
||||
* <p><strong>This is an evolving set.</strong> Future releases may drop
|
||||
* support for transitional transports (like spdy/3), in favor of their
|
||||
* support for transitional protocols (like spdy/3), in favor of their
|
||||
* successors (spdy/4 or http/2.0). The http/1.1 transport will never be
|
||||
* dropped.
|
||||
*
|
||||
@@ -319,28 +338,41 @@ public final class OkHttpClient implements URLStreamHandlerFactory, Cloneable {
|
||||
* (such as <a href="http://tools.ietf.org/html/draft-friedl-tls-applayerprotoneg-02">ALPN</a>)
|
||||
* to negotiate a transport.
|
||||
*
|
||||
* @param transports the transports to use, in order of preference. The list
|
||||
* @param protocols the protocols to use, in order of preference. The list
|
||||
* must contain "http/1.1". It must not contain null.
|
||||
*/
|
||||
public OkHttpClient setTransports(List<String> transports) {
|
||||
transports = Util.immutableList(transports);
|
||||
if (!transports.contains("http/1.1")) {
|
||||
throw new IllegalArgumentException("transports doesn't contain http/1.1: " + transports);
|
||||
public OkHttpClient setProtocols(List<Protocol> protocols) {
|
||||
protocols = Util.immutableList(protocols);
|
||||
if (!protocols.contains(Protocol.HTTP_11)) {
|
||||
throw new IllegalArgumentException("protocols doesn't contain http/1.1: " + protocols);
|
||||
}
|
||||
if (transports.contains(null)) {
|
||||
throw new IllegalArgumentException("transports must not contain null");
|
||||
if (protocols.contains(null)) {
|
||||
throw new IllegalArgumentException("protocols must not contain null");
|
||||
}
|
||||
if (transports.contains("")) {
|
||||
throw new IllegalArgumentException("transports contains an empty string");
|
||||
if (protocols.contains(ByteString.EMPTY)) {
|
||||
throw new IllegalArgumentException("protocols contains an empty string");
|
||||
}
|
||||
this.transports = transports;
|
||||
this.protocols = Util.immutableList(protocols);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated OkHttp 2 enforces an enumeration of {@link Protocol protocols}
|
||||
* that can be selected. Please switch to {@link #getProtocols()}.
|
||||
*/
|
||||
@Deprecated
|
||||
public List<String> getTransports() {
|
||||
List<String> transports = new ArrayList<String>(protocols.size());
|
||||
for (int i = 0, size = protocols.size(); i < size; i++) {
|
||||
transports.add(protocols.get(i).name.utf8());
|
||||
}
|
||||
return transports;
|
||||
}
|
||||
|
||||
public List<Protocol> getProtocols() {
|
||||
return protocols;
|
||||
}
|
||||
|
||||
/**
|
||||
* Schedules {@code request} to be executed at some point in the future. The
|
||||
* {@link #getDispatcher dispatcher} defines when the request will run:
|
||||
@@ -404,8 +436,8 @@ public final class OkHttpClient implements URLStreamHandlerFactory, Cloneable {
|
||||
if (result.connectionPool == null) {
|
||||
result.connectionPool = ConnectionPool.getDefault();
|
||||
}
|
||||
if (result.transports == null) {
|
||||
result.transports = DEFAULT_TRANSPORTS;
|
||||
if (result.protocols == null) {
|
||||
result.protocols = Protocol.HTTP2_SPDY3_AND_HTTP;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -218,7 +218,7 @@ public final class Response {
|
||||
|
||||
/**
|
||||
* Returns true if further data from this response body should be read at
|
||||
* this time. For asynchronous transports like SPDY and HTTP/2.0, this will
|
||||
* this time. For asynchronous protocols like SPDY and HTTP/2.0, this will
|
||||
* return false once all locally-available body bytes have been read.
|
||||
*
|
||||
* <p>Clients with many concurrent downloads can use this method to reduce
|
||||
|
||||
@@ -234,7 +234,7 @@ public class HttpEngine {
|
||||
hostnameVerifier = client.getHostnameVerifier();
|
||||
}
|
||||
Address address = new Address(uriHost, getEffectivePort(request.url()), sslSocketFactory,
|
||||
hostnameVerifier, client.getAuthenticator(), client.getProxy(), client.getTransports());
|
||||
hostnameVerifier, client.getAuthenticator(), client.getProxy(), client.getProtocols());
|
||||
routeSelector = new RouteSelector(address, request.uri(), client.getProxySelector(),
|
||||
client.getConnectionPool(), Dns.DEFAULT, client.getRoutesDatabase());
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ import com.squareup.okhttp.Headers;
|
||||
import com.squareup.okhttp.Request;
|
||||
import com.squareup.okhttp.Response;
|
||||
import com.squareup.okhttp.internal.AbstractOutputStream;
|
||||
import com.squareup.okhttp.Protocol;
|
||||
import com.squareup.okhttp.internal.Util;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
@@ -155,7 +156,8 @@ public final class HttpTransport implements Transport {
|
||||
|
||||
Response.Builder responseBuilder = new Response.Builder()
|
||||
.statusLine(statusLine)
|
||||
.header(OkHeaders.SELECTED_TRANSPORT, "http/1.1");
|
||||
.header(OkHeaders.SELECTED_TRANSPORT, Protocol.HTTP_11.name.utf8())
|
||||
.header(OkHeaders.SELECTED_PROTOCOL, Protocol.HTTP_11.name.utf8());
|
||||
|
||||
Headers.Builder headersBuilder = new Headers.Builder();
|
||||
OkHeaders.readHeaders(headersBuilder, in);
|
||||
|
||||
@@ -23,7 +23,9 @@ import com.squareup.okhttp.OkHttpClient;
|
||||
import com.squareup.okhttp.Request;
|
||||
import com.squareup.okhttp.Response;
|
||||
import com.squareup.okhttp.Route;
|
||||
import com.squareup.okhttp.internal.ByteString;
|
||||
import com.squareup.okhttp.internal.Platform;
|
||||
import com.squareup.okhttp.Protocol;
|
||||
import com.squareup.okhttp.internal.Util;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
@@ -502,8 +504,9 @@ public class HttpURLConnectionImpl extends HttpURLConnection {
|
||||
return;
|
||||
}
|
||||
|
||||
if ("X-Android-Transports".equals(field)) {
|
||||
setTransports(newValue, false /* append */);
|
||||
// TODO: Deprecate use of X-Android-Transports header?
|
||||
if ("X-Android-Transports".equals(field) || "X-Android-Protocols".equals(field)) {
|
||||
setProtocols(newValue, false /* append */);
|
||||
} else {
|
||||
requestHeaders.set(field, newValue);
|
||||
}
|
||||
@@ -535,26 +538,33 @@ public class HttpURLConnectionImpl extends HttpURLConnection {
|
||||
return;
|
||||
}
|
||||
|
||||
if ("X-Android-Transports".equals(field)) {
|
||||
setTransports(value, true /* append */);
|
||||
// TODO: Deprecate use of X-Android-Transports header?
|
||||
if ("X-Android-Transports".equals(field) || "X-Android-Protocols".equals(field)) {
|
||||
setProtocols(value, true /* append */);
|
||||
} else {
|
||||
requestHeaders.add(field, value);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Splits and validates a comma-separated string of transports.
|
||||
* Splits and validates a comma-separated string of protocols.
|
||||
* When append == false, we require that the transport list contains "http/1.1".
|
||||
* Throws {@link IllegalStateException} when one of the protocols isn't
|
||||
* defined in {@link Protocol OkHttp's protocol enumeration}.
|
||||
*/
|
||||
private void setTransports(String transportsString, boolean append) {
|
||||
List<String> transportsList = new ArrayList<String>();
|
||||
private void setProtocols(String protocolsString, boolean append) {
|
||||
List<Protocol> protocolsList = new ArrayList<Protocol>();
|
||||
if (append) {
|
||||
transportsList.addAll(client.getTransports());
|
||||
protocolsList.addAll(client.getProtocols());
|
||||
}
|
||||
for (String transport : transportsString.split(",", -1)) {
|
||||
transportsList.add(transport);
|
||||
for (ByteString protocol : Util.byteStringList(protocolsString.split(",", -1))) {
|
||||
try {
|
||||
protocolsList.add(Protocol.find(protocol));
|
||||
} catch (IOException e) {
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
}
|
||||
client.setTransports(transportsList);
|
||||
client.setProtocols(protocolsList);
|
||||
}
|
||||
|
||||
@Override public void setFixedLengthStreamingMode(int contentLength) {
|
||||
|
||||
@@ -50,10 +50,18 @@ public final class OkHeaders {
|
||||
public static final String RESPONSE_SOURCE = PREFIX + "-Response-Source";
|
||||
|
||||
/**
|
||||
* Synthetic response header: the selected transport ("spdy/3", "http/1.1", etc).
|
||||
* @deprecated OkHttp 2 enforces an enumeration of {@link com.squareup.okhttp.Protocol protocols}
|
||||
* that can be selected. Please use #SELECTED_PROTOCOL
|
||||
*/
|
||||
@Deprecated
|
||||
public static final String SELECTED_TRANSPORT = PREFIX + "-Selected-Transport";
|
||||
|
||||
/**
|
||||
* Synthetic response header: the selected
|
||||
* {@link com.squareup.okhttp.Protocol protocol} ("spdy/3", "http/1.1", etc).
|
||||
*/
|
||||
public static final String SELECTED_PROTOCOL = PREFIX + "-Selected-Protocol";
|
||||
|
||||
private OkHeaders() {
|
||||
}
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ import com.squareup.okhttp.Headers;
|
||||
import com.squareup.okhttp.Request;
|
||||
import com.squareup.okhttp.Response;
|
||||
import com.squareup.okhttp.internal.ByteString;
|
||||
import com.squareup.okhttp.Protocol;
|
||||
import com.squareup.okhttp.internal.spdy.ErrorCode;
|
||||
import com.squareup.okhttp.internal.spdy.SpdyConnection;
|
||||
import com.squareup.okhttp.internal.spdy.SpdyStream;
|
||||
@@ -41,7 +42,6 @@ public final class SpdyTransport implements Transport {
|
||||
private static final ByteString HEADER_HOST = ByteString.encodeUtf8(":host");
|
||||
private static final ByteString HEADER_AUTHORITY = ByteString.encodeUtf8(":authority");
|
||||
private static final ByteString HEADER_SCHEME = ByteString.encodeUtf8(":scheme");
|
||||
private static final ByteString NULL = ByteString.of((byte) 0x00);
|
||||
|
||||
private final HttpEngine httpEngine;
|
||||
private final SpdyConnection spdyConnection;
|
||||
@@ -88,7 +88,7 @@ public final class SpdyTransport implements Transport {
|
||||
* Names are all lower case. No names are repeated. If any name has multiple
|
||||
* values, they are concatenated using "\0" as a delimiter.
|
||||
*/
|
||||
public static List<ByteString> writeNameValueBlock(Request request, String protocol,
|
||||
public static List<ByteString> writeNameValueBlock(Request request, Protocol protocol,
|
||||
String version) {
|
||||
Headers headers = request.headers();
|
||||
// TODO: make the known header names constants.
|
||||
@@ -99,9 +99,9 @@ public final class SpdyTransport implements Transport {
|
||||
result.add(ByteString.encodeUtf8(RequestLine.requestPath(request.url())));
|
||||
result.add(HEADER_VERSION);
|
||||
result.add(ByteString.encodeUtf8(version));
|
||||
if (protocol.equals("spdy/3")) {
|
||||
if (Protocol.SPDY_3 == protocol) {
|
||||
result.add(HEADER_HOST);
|
||||
} else if (protocol.equals("HTTP-draft-09/2.0")) {
|
||||
} else if (Protocol.HTTP_2 == protocol) {
|
||||
result.add(HEADER_AUTHORITY);
|
||||
} else {
|
||||
throw new AssertionError();
|
||||
@@ -127,19 +127,19 @@ public final class SpdyTransport implements Transport {
|
||||
|| name.equals(":scheme")) {
|
||||
continue;
|
||||
}
|
||||
ByteString valueBytes = ByteString.encodeUtf8(value);
|
||||
|
||||
// If we haven't seen this name before, add the pair to the end of the list...
|
||||
if (names.add(ByteString.encodeUtf8(name))) {
|
||||
result.add(ByteString.encodeUtf8(name));
|
||||
result.add(valueBytes);
|
||||
result.add(ByteString.encodeUtf8(value));
|
||||
continue;
|
||||
}
|
||||
|
||||
// ...otherwise concatenate the existing values and this value.
|
||||
for (int j = 0; j < result.size(); j += 2) {
|
||||
if (result.get(j).utf8Equals(name)) {
|
||||
result.set(j + 1, ByteString.concat(result.get(j + 1), NULL, valueBytes));
|
||||
String concatenated = joinOnNull(result.get(j + 1).utf8(), value);
|
||||
result.set(j + 1, ByteString.encodeUtf8(concatenated));
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -147,9 +147,13 @@ public final class SpdyTransport implements Transport {
|
||||
return result;
|
||||
}
|
||||
|
||||
private static String joinOnNull(String first, String second) {
|
||||
return new StringBuilder(first).append('\0').append(second).toString();
|
||||
}
|
||||
|
||||
/** Returns headers for a name value block containing a SPDY response. */
|
||||
public static Response.Builder readNameValueBlock(List<ByteString> nameValueBlock,
|
||||
String protocol) throws IOException {
|
||||
Protocol protocol) throws IOException {
|
||||
if (nameValueBlock.size() % 2 != 0) {
|
||||
throw new IllegalArgumentException("Unexpected name value block: " + nameValueBlock);
|
||||
}
|
||||
@@ -157,7 +161,8 @@ public final class SpdyTransport implements Transport {
|
||||
String version = "HTTP/1.1"; // TODO: why are we expecting :version?
|
||||
|
||||
Headers.Builder headersBuilder = new Headers.Builder();
|
||||
headersBuilder.set(OkHeaders.SELECTED_TRANSPORT, protocol);
|
||||
headersBuilder.set(OkHeaders.SELECTED_TRANSPORT, protocol.name.utf8());
|
||||
headersBuilder.set(OkHeaders.SELECTED_PROTOCOL, protocol.name.utf8());
|
||||
for (int i = 0; i < nameValueBlock.size(); i += 2) {
|
||||
String name = nameValueBlock.get(i).utf8();
|
||||
String values = nameValueBlock.get(i + 1).utf8();
|
||||
@@ -206,9 +211,9 @@ public final class SpdyTransport implements Transport {
|
||||
}
|
||||
|
||||
/** When true, this header should not be emitted or consumed. */
|
||||
private static boolean isProhibitedHeader(String protocol, String name) {
|
||||
private static boolean isProhibitedHeader(Protocol protocol, String name) {
|
||||
boolean prohibited = false;
|
||||
if (protocol.equals("spdy/3")) {
|
||||
if (protocol == Protocol.SPDY_3) {
|
||||
// http://www.chromium.org/spdy/spdy-protocol/spdy-protocol-draft3#TOC-3.2.1-Request
|
||||
if (name.equals("connection")
|
||||
|| name.equals("host")
|
||||
@@ -217,7 +222,7 @@ public final class SpdyTransport implements Transport {
|
||||
|| name.equals("transfer-encoding")) {
|
||||
prohibited = true;
|
||||
}
|
||||
} else if (protocol.equals("HTTP-draft-09/2.0")) {
|
||||
} else if (protocol == Protocol.HTTP_2) {
|
||||
// http://tools.ietf.org/html/draft-ietf-httpbis-http2-09#section-8.1.3
|
||||
if (name.equals("connection")
|
||||
|| name.equals("host")
|
||||
@@ -230,7 +235,7 @@ public final class SpdyTransport implements Transport {
|
||||
prohibited = true;
|
||||
}
|
||||
} else {
|
||||
throw new AssertionError();
|
||||
throw new AssertionError(protocol);
|
||||
}
|
||||
return prohibited;
|
||||
}
|
||||
|
||||
@@ -61,14 +61,14 @@ public final class ConnectionPoolTest {
|
||||
|
||||
httpServer.play();
|
||||
httpAddress = new Address(httpServer.getHostName(), httpServer.getPort(), null, null,
|
||||
HttpAuthenticator.SYSTEM_DEFAULT, null, Arrays.asList("spdy/3", "http/1.1"));
|
||||
HttpAuthenticator.SYSTEM_DEFAULT, null, Protocol.SPDY3_AND_HTTP11);
|
||||
httpSocketAddress = new InetSocketAddress(InetAddress.getByName(httpServer.getHostName()),
|
||||
httpServer.getPort());
|
||||
|
||||
spdyServer.play();
|
||||
spdyAddress = new Address(spdyServer.getHostName(), spdyServer.getPort(),
|
||||
sslContext.getSocketFactory(), new RecordingHostnameVerifier(),
|
||||
HttpAuthenticator.SYSTEM_DEFAULT, null, Arrays.asList("spdy/3", "http/1.1"));
|
||||
HttpAuthenticator.SYSTEM_DEFAULT, null,Protocol.SPDY3_AND_HTTP11);
|
||||
spdySocketAddress = new InetSocketAddress(InetAddress.getByName(spdyServer.getHostName()),
|
||||
spdyServer.getPort());
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@ import com.squareup.okhttp.Headers;
|
||||
import com.squareup.okhttp.Request;
|
||||
import com.squareup.okhttp.Response;
|
||||
import com.squareup.okhttp.internal.ByteString;
|
||||
import com.squareup.okhttp.Protocol;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import org.junit.Test;
|
||||
@@ -36,21 +37,23 @@ public final class HeadersTest {
|
||||
":version", "HTTP/1.1");
|
||||
Request request = new Request.Builder().url("http://square.com/").build();
|
||||
Response response =
|
||||
SpdyTransport.readNameValueBlock(nameValueBlock, "spdy/3").request(request).build();
|
||||
SpdyTransport.readNameValueBlock(nameValueBlock, Protocol.SPDY_3).request(request).build();
|
||||
Headers headers = response.headers();
|
||||
assertEquals(4, headers.size());
|
||||
assertEquals(5, headers.size());
|
||||
assertEquals("HTTP/1.1 200 OK", response.statusLine());
|
||||
assertEquals("no-cache, no-store", headers.get("cache-control"));
|
||||
assertEquals("Cookie2", headers.get("set-cookie"));
|
||||
assertEquals("spdy/3", headers.get(OkHeaders.SELECTED_TRANSPORT));
|
||||
assertEquals(Protocol.SPDY_3.name.utf8(), headers.get(OkHeaders.SELECTED_TRANSPORT));
|
||||
assertEquals(OkHeaders.SELECTED_TRANSPORT, headers.name(0));
|
||||
assertEquals("spdy/3", headers.value(0));
|
||||
assertEquals("cache-control", headers.name(1));
|
||||
assertEquals("no-cache, no-store", headers.value(1));
|
||||
assertEquals("set-cookie", headers.name(2));
|
||||
assertEquals("Cookie1", headers.value(2));
|
||||
assertEquals(Protocol.SPDY_3.name.utf8(), headers.get(OkHeaders.SELECTED_PROTOCOL));
|
||||
assertEquals(OkHeaders.SELECTED_PROTOCOL, headers.name(1));
|
||||
assertEquals(Protocol.SPDY_3.name.utf8(), headers.value(1));
|
||||
assertEquals("cache-control", headers.name(2));
|
||||
assertEquals("no-cache, no-store", headers.value(2));
|
||||
assertEquals("set-cookie", headers.name(3));
|
||||
assertEquals("Cookie2", headers.value(3));
|
||||
assertEquals("Cookie1", headers.value(3));
|
||||
assertEquals("set-cookie", headers.name(4));
|
||||
assertEquals("Cookie2", headers.value(4));
|
||||
assertNull(headers.get(":status"));
|
||||
assertNull(headers.get(":version"));
|
||||
}
|
||||
@@ -62,11 +65,13 @@ public final class HeadersTest {
|
||||
"connection", "close");
|
||||
Request request = new Request.Builder().url("http://square.com/").build();
|
||||
Response response =
|
||||
SpdyTransport.readNameValueBlock(nameValueBlock, "spdy/3").request(request).build();
|
||||
SpdyTransport.readNameValueBlock(nameValueBlock, Protocol.SPDY_3).request(request).build();
|
||||
Headers headers = response.headers();
|
||||
assertEquals(1, headers.size());
|
||||
assertEquals(2, headers.size());
|
||||
assertEquals(OkHeaders.SELECTED_TRANSPORT, headers.name(0));
|
||||
assertEquals("spdy/3", headers.value(0));;
|
||||
assertEquals(Protocol.SPDY_3.name.utf8(), headers.value(0));
|
||||
assertEquals(OkHeaders.SELECTED_PROTOCOL, headers.name(1));
|
||||
assertEquals(Protocol.SPDY_3.name.utf8(), headers.value(1));;
|
||||
}
|
||||
|
||||
@Test public void readNameValueBlockDropsForbiddenHeadersHttp2() throws IOException {
|
||||
@@ -75,12 +80,14 @@ public final class HeadersTest {
|
||||
":version", "HTTP/1.1",
|
||||
"connection", "close");
|
||||
Request request = new Request.Builder().url("http://square.com/").build();
|
||||
Response response =
|
||||
SpdyTransport.readNameValueBlock(nameValueBlock, "HTTP-draft-09/2.0").request(request).build();
|
||||
Response response = SpdyTransport.readNameValueBlock(nameValueBlock, Protocol.HTTP_2)
|
||||
.request(request).build();
|
||||
Headers headers = response.headers();
|
||||
assertEquals(1, headers.size());
|
||||
assertEquals(2, headers.size());
|
||||
assertEquals(OkHeaders.SELECTED_TRANSPORT, headers.name(0));
|
||||
assertEquals("HTTP-draft-09/2.0", headers.value(0));;
|
||||
assertEquals(Protocol.HTTP_2.name.utf8(), headers.value(0));
|
||||
assertEquals(OkHeaders.SELECTED_PROTOCOL, headers.name(1));
|
||||
assertEquals(Protocol.HTTP_2.name.utf8(), headers.value(1));
|
||||
}
|
||||
|
||||
@Test public void toNameValueBlock() {
|
||||
@@ -91,7 +98,8 @@ public final class HeadersTest {
|
||||
.addHeader("set-cookie", "Cookie2")
|
||||
.header(":status", "200 OK")
|
||||
.build();
|
||||
List<ByteString> nameValueBlock = SpdyTransport.writeNameValueBlock(request, "spdy/3", "HTTP/1.1");
|
||||
List<ByteString> nameValueBlock =
|
||||
SpdyTransport.writeNameValueBlock(request, Protocol.SPDY_3, "HTTP/1.1");
|
||||
List<ByteString> expected = byteStringList(
|
||||
":method", "GET",
|
||||
":path", "/",
|
||||
@@ -116,7 +124,7 @@ public final class HeadersTest {
|
||||
":version", "HTTP/1.1",
|
||||
":host", "square.com",
|
||||
":scheme", "http");
|
||||
assertEquals(expected, SpdyTransport.writeNameValueBlock(request, "spdy/3", "HTTP/1.1"));
|
||||
assertEquals(expected, SpdyTransport.writeNameValueBlock(request, Protocol.SPDY_3, "HTTP/1.1"));
|
||||
}
|
||||
|
||||
@Test public void toNameValueBlockDropsForbiddenHeadersHttp2() {
|
||||
@@ -132,6 +140,6 @@ public final class HeadersTest {
|
||||
":authority", "square.com",
|
||||
":scheme", "http");
|
||||
assertEquals(expected,
|
||||
SpdyTransport.writeNameValueBlock(request, "HTTP-draft-09/2.0", "HTTP/1.1"));
|
||||
SpdyTransport.writeNameValueBlock(request, Protocol.HTTP_2, "HTTP/1.1"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,12 +15,12 @@
|
||||
*/
|
||||
package com.squareup.okhttp.internal.http;
|
||||
|
||||
import com.squareup.okhttp.Protocol;
|
||||
|
||||
public class HttpOverHttp20Draft09Test extends HttpOverSpdyTest {
|
||||
|
||||
public HttpOverHttp20Draft09Test() {
|
||||
super("HTTP-draft-09/2.0");
|
||||
// TODO: is this really the whole authority, or just the host/port?
|
||||
// https://github.com/http2/http2-spec/issues/334
|
||||
super(Protocol.HTTP_2);
|
||||
this.hostHeader = ":authority";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,9 +15,11 @@
|
||||
*/
|
||||
package com.squareup.okhttp.internal.http;
|
||||
|
||||
import com.squareup.okhttp.Protocol;
|
||||
|
||||
public class HttpOverSpdy3Test extends HttpOverSpdyTest {
|
||||
|
||||
public HttpOverSpdy3Test() {
|
||||
super("spdy/3");
|
||||
super(Protocol.SPDY_3);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ package com.squareup.okhttp.internal.http;
|
||||
|
||||
import com.squareup.okhttp.HttpResponseCache;
|
||||
import com.squareup.okhttp.OkHttpClient;
|
||||
import com.squareup.okhttp.Protocol;
|
||||
import com.squareup.okhttp.internal.RecordingAuthenticator;
|
||||
import com.squareup.okhttp.internal.SslContextBuilder;
|
||||
import com.squareup.okhttp.internal.Util;
|
||||
@@ -61,12 +62,12 @@ import static org.junit.Assert.fail;
|
||||
/** Test how SPDY interacts with HTTP features. */
|
||||
public abstract class HttpOverSpdyTest {
|
||||
|
||||
/** Transport to test, for example {@code spdy/3} */
|
||||
private final String transport;
|
||||
/** Protocol to test, for example {@link com.squareup.okhttp.Protocol#SPDY_3} */
|
||||
private final Protocol protocol;
|
||||
protected String hostHeader = ":host";
|
||||
|
||||
protected HttpOverSpdyTest(String transport){
|
||||
this.transport = transport;
|
||||
protected HttpOverSpdyTest(Protocol protocol){
|
||||
this.protocol = protocol;
|
||||
}
|
||||
|
||||
private static final HostnameVerifier NULL_HOSTNAME_VERIFIER = new HostnameVerifier() {
|
||||
@@ -83,11 +84,11 @@ public abstract class HttpOverSpdyTest {
|
||||
|
||||
@Before public void setUp() throws Exception {
|
||||
server.useHttps(sslContext.getSocketFactory(), false);
|
||||
client.setTransports(Arrays.asList(transport, "http/1.1"));
|
||||
client.setProtocols(Arrays.asList(protocol, Protocol.HTTP_11));
|
||||
client.setSslSocketFactory(sslContext.getSocketFactory());
|
||||
client.setHostnameVerifier(NULL_HOSTNAME_VERIFIER);
|
||||
String systemTmpDir = System.getProperty("java.io.tmpdir");
|
||||
File cacheDir = new File(systemTmpDir, "HttpCache-" + transport + "-" + UUID.randomUUID());
|
||||
File cacheDir = new File(systemTmpDir, "HttpCache-" + protocol + "-" + UUID.randomUUID());
|
||||
cache = new HttpResponseCache(cacheDir, Integer.MAX_VALUE);
|
||||
}
|
||||
|
||||
@@ -386,8 +387,7 @@ public abstract class HttpOverSpdyTest {
|
||||
|
||||
@Override public void run() {
|
||||
try {
|
||||
HttpURLConnection conn = null;
|
||||
conn = (HttpURLConnection) client.open(server.getUrl(path));
|
||||
HttpURLConnection conn = client.open(server.getUrl(path));
|
||||
assertEquals("A", readAscii(conn.getInputStream(), 1));
|
||||
countDownLatch.countDown();
|
||||
} catch (Exception e) {
|
||||
|
||||
@@ -21,6 +21,7 @@ import com.squareup.okhttp.ConnectionPool;
|
||||
import com.squareup.okhttp.OkAuthenticator;
|
||||
import com.squareup.okhttp.RouteDatabase;
|
||||
import com.squareup.okhttp.internal.Dns;
|
||||
import com.squareup.okhttp.Protocol;
|
||||
import com.squareup.okhttp.internal.SslContextBuilder;
|
||||
import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
@@ -75,12 +76,12 @@ public final class RouteSelectorTest {
|
||||
}
|
||||
|
||||
private final OkAuthenticator authenticator = HttpAuthenticator.SYSTEM_DEFAULT;
|
||||
private final List<String> transports = Arrays.asList("http/1.1");
|
||||
private final List<Protocol> protocols = Arrays.asList(Protocol.HTTP_11);
|
||||
private final FakeDns dns = new FakeDns();
|
||||
private final FakeProxySelector proxySelector = new FakeProxySelector();
|
||||
|
||||
@Test public void singleRoute() throws Exception {
|
||||
Address address = new Address(uriHost, uriPort, null, null, authenticator, null, transports);
|
||||
Address address = new Address(uriHost, uriPort, null, null, authenticator, null, protocols);
|
||||
RouteSelector routeSelector = new RouteSelector(address, uri, proxySelector, pool, dns,
|
||||
new RouteDatabase());
|
||||
|
||||
@@ -99,7 +100,7 @@ public final class RouteSelectorTest {
|
||||
}
|
||||
|
||||
@Test public void singleRouteReturnsFailedRoute() throws Exception {
|
||||
Address address = new Address(uriHost, uriPort, null, null, authenticator, null, transports);
|
||||
Address address = new Address(uriHost, uriPort, null, null, authenticator, null, protocols);
|
||||
RouteSelector routeSelector = new RouteSelector(address, uri, proxySelector, pool, dns,
|
||||
new RouteDatabase());
|
||||
|
||||
@@ -120,7 +121,7 @@ public final class RouteSelectorTest {
|
||||
}
|
||||
|
||||
@Test public void explicitProxyTriesThatProxiesAddressesOnly() throws Exception {
|
||||
Address address = new Address(uriHost, uriPort, null, null, authenticator, proxyA, transports);
|
||||
Address address = new Address(uriHost, uriPort, null, null, authenticator, proxyA, protocols);
|
||||
RouteSelector routeSelector = new RouteSelector(address, uri, proxySelector, pool, dns,
|
||||
new RouteDatabase());
|
||||
|
||||
@@ -138,7 +139,7 @@ public final class RouteSelectorTest {
|
||||
|
||||
@Test public void explicitDirectProxy() throws Exception {
|
||||
Address address = new Address(uriHost, uriPort, null, null, authenticator, NO_PROXY,
|
||||
transports);
|
||||
protocols);
|
||||
RouteSelector routeSelector = new RouteSelector(address, uri, proxySelector, pool, dns,
|
||||
new RouteDatabase());
|
||||
|
||||
@@ -155,7 +156,7 @@ public final class RouteSelectorTest {
|
||||
}
|
||||
|
||||
@Test public void proxySelectorReturnsNull() throws Exception {
|
||||
Address address = new Address(uriHost, uriPort, null, null, authenticator, null, transports);
|
||||
Address address = new Address(uriHost, uriPort, null, null, authenticator, null, protocols);
|
||||
|
||||
proxySelector.proxies = null;
|
||||
RouteSelector routeSelector = new RouteSelector(address, uri, proxySelector, pool, dns,
|
||||
@@ -172,7 +173,7 @@ public final class RouteSelectorTest {
|
||||
}
|
||||
|
||||
@Test public void proxySelectorReturnsNoProxies() throws Exception {
|
||||
Address address = new Address(uriHost, uriPort, null, null, authenticator, null, transports);
|
||||
Address address = new Address(uriHost, uriPort, null, null, authenticator, null, protocols);
|
||||
RouteSelector routeSelector = new RouteSelector(address, uri, proxySelector, pool, dns,
|
||||
new RouteDatabase());
|
||||
|
||||
@@ -189,7 +190,7 @@ public final class RouteSelectorTest {
|
||||
}
|
||||
|
||||
@Test public void proxySelectorReturnsMultipleProxies() throws Exception {
|
||||
Address address = new Address(uriHost, uriPort, null, null, authenticator, null, transports);
|
||||
Address address = new Address(uriHost, uriPort, null, null, authenticator, null, protocols);
|
||||
|
||||
proxySelector.proxies.add(proxyA);
|
||||
proxySelector.proxies.add(proxyB);
|
||||
@@ -224,7 +225,7 @@ public final class RouteSelectorTest {
|
||||
}
|
||||
|
||||
@Test public void proxySelectorDirectConnectionsAreSkipped() throws Exception {
|
||||
Address address = new Address(uriHost, uriPort, null, null, authenticator, null, transports);
|
||||
Address address = new Address(uriHost, uriPort, null, null, authenticator, null, protocols);
|
||||
|
||||
proxySelector.proxies.add(NO_PROXY);
|
||||
RouteSelector routeSelector = new RouteSelector(address, uri, proxySelector, pool, dns,
|
||||
@@ -242,7 +243,7 @@ public final class RouteSelectorTest {
|
||||
}
|
||||
|
||||
@Test public void proxyDnsFailureContinuesToNextProxy() throws Exception {
|
||||
Address address = new Address(uriHost, uriPort, null, null, authenticator, null, transports);
|
||||
Address address = new Address(uriHost, uriPort, null, null, authenticator, null, protocols);
|
||||
|
||||
proxySelector.proxies.add(proxyA);
|
||||
proxySelector.proxies.add(proxyB);
|
||||
@@ -284,7 +285,7 @@ public final class RouteSelectorTest {
|
||||
// https://github.com/square/okhttp/issues/442
|
||||
@Test public void nonSslErrorAddsAllTlsModesToFailedRoute() throws Exception {
|
||||
Address address = new Address(uriHost, uriPort, socketFactory, hostnameVerifier, authenticator,
|
||||
Proxy.NO_PROXY, transports);
|
||||
Proxy.NO_PROXY, protocols);
|
||||
RouteDatabase routeDatabase = new RouteDatabase();
|
||||
RouteSelector routeSelector = new RouteSelector(address, uri, proxySelector, pool, dns,
|
||||
routeDatabase);
|
||||
@@ -298,7 +299,7 @@ public final class RouteSelectorTest {
|
||||
|
||||
@Test public void sslErrorAddsOnlyFailedTlsModeToFailedRoute() throws Exception {
|
||||
Address address = new Address(uriHost, uriPort, socketFactory, hostnameVerifier, authenticator,
|
||||
Proxy.NO_PROXY, transports);
|
||||
Proxy.NO_PROXY, protocols);
|
||||
RouteDatabase routeDatabase = new RouteDatabase();
|
||||
RouteSelector routeSelector = new RouteSelector(address, uri, proxySelector, pool, dns,
|
||||
routeDatabase);
|
||||
@@ -312,7 +313,7 @@ public final class RouteSelectorTest {
|
||||
|
||||
@Test public void multipleProxiesMultipleInetAddressesMultipleTlsModes() throws Exception {
|
||||
Address address = new Address(uriHost, uriPort, socketFactory, hostnameVerifier, authenticator,
|
||||
null, transports);
|
||||
null, protocols);
|
||||
proxySelector.proxies.add(proxyA);
|
||||
proxySelector.proxies.add(proxyB);
|
||||
RouteSelector routeSelector = new RouteSelector(address, uri, proxySelector, pool, dns,
|
||||
@@ -359,7 +360,7 @@ public final class RouteSelectorTest {
|
||||
|
||||
@Test public void failedRoutesAreLast() throws Exception {
|
||||
Address address = new Address(uriHost, uriPort, socketFactory, hostnameVerifier, authenticator,
|
||||
Proxy.NO_PROXY, transports);
|
||||
Proxy.NO_PROXY, protocols);
|
||||
|
||||
RouteDatabase routeDatabase = new RouteDatabase();
|
||||
RouteSelector routeSelector = new RouteSelector(address, uri, proxySelector, pool, dns,
|
||||
|
||||
@@ -18,6 +18,7 @@ package com.squareup.okhttp.internal.http;
|
||||
|
||||
import com.squareup.okhttp.HttpResponseCache;
|
||||
import com.squareup.okhttp.OkHttpClient;
|
||||
import com.squareup.okhttp.Protocol;
|
||||
import com.squareup.okhttp.internal.RecordingAuthenticator;
|
||||
import com.squareup.okhttp.internal.RecordingHostnameVerifier;
|
||||
import com.squareup.okhttp.internal.RecordingOkAuthenticator;
|
||||
@@ -2500,24 +2501,24 @@ public final class URLConnectionTest {
|
||||
assertTrue(call, call.contains("challenges=[Basic realm=\"protected area\"]"));
|
||||
}
|
||||
|
||||
@Test public void setTransports() throws Exception {
|
||||
@Test public void setProtocols() throws Exception {
|
||||
server.enqueue(new MockResponse().setBody("A"));
|
||||
server.play();
|
||||
client.setTransports(Arrays.asList("http/1.1"));
|
||||
client.setProtocols(Arrays.asList(Protocol.HTTP_11));
|
||||
assertContent("A", client.open(server.getUrl("/")));
|
||||
}
|
||||
|
||||
@Test public void setTransportsWithoutHttp11() throws Exception {
|
||||
@Test public void setProtocolsWithoutHttp11() throws Exception {
|
||||
try {
|
||||
client.setTransports(Arrays.asList("spdy/3"));
|
||||
client.setProtocols(Arrays.asList(Protocol.SPDY_3));
|
||||
fail();
|
||||
} catch (IllegalArgumentException expected) {
|
||||
}
|
||||
}
|
||||
|
||||
@Test public void setTransportsWithNull() throws Exception {
|
||||
@Test public void setProtocolsWithNull() throws Exception {
|
||||
try {
|
||||
client.setTransports(Arrays.asList("http/1.1", null));
|
||||
client.setProtocols(Arrays.asList(Protocol.HTTP_11, null));
|
||||
fail();
|
||||
} catch (IllegalArgumentException expected) {
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user