1
0
mirror of https://github.com/square/okhttp.git synced 2026-01-25 16:01:38 +03:00

Teach MockWebServer SPDY.

Kill MockSpdyServer in the process.
This commit is contained in:
jwilson
2013-08-05 18:09:31 -04:00
parent 894743dd5c
commit 00a50d1919
12 changed files with 200 additions and 300 deletions

View File

@@ -1,263 +0,0 @@
/*
* Copyright (C) 2013 Square, Inc.
* Copyright (C) 2011 The Android Open Source Project
*
* 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.internal.mockspdyserver;
import com.squareup.okhttp.mockwebserver.MockResponse;
import com.squareup.okhttp.mockwebserver.QueueDispatcher;
import com.squareup.okhttp.mockwebserver.RecordedRequest;
import com.squareup.okhttp.internal.Platform;
import com.squareup.okhttp.internal.spdy.IncomingStreamHandler;
import com.squareup.okhttp.internal.spdy.SpdyConnection;
import com.squareup.okhttp.internal.spdy.SpdyStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.InetAddress;
import java.net.MalformedURLException;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.net.URL;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Set;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
/** A scriptable spdy/3 + HTTP server. */
public final class MockSpdyServer {
private static final byte[] NPN_PROTOCOLS = new byte[] { 6, 's', 'p', 'd', 'y', '/', '3', };
private static final Logger logger = Logger.getLogger(MockSpdyServer.class.getName());
private SSLSocketFactory sslSocketFactory;
private QueueDispatcher dispatcher = new QueueDispatcher();
private ServerSocket serverSocket;
private final Set<Socket> openClientSockets =
Collections.newSetFromMap(new ConcurrentHashMap<Socket, Boolean>());
private int port = -1;
private final BlockingQueue<RecordedRequest> requestQueue =
new LinkedBlockingQueue<RecordedRequest>();
public MockSpdyServer(SSLSocketFactory sslSocketFactory) {
this.sslSocketFactory = sslSocketFactory;
}
public String getHostName() {
try {
return InetAddress.getLocalHost().getHostName();
} catch (UnknownHostException e) {
throw new AssertionError();
}
}
public int getPort() {
if (port == -1) {
throw new IllegalStateException("Cannot retrieve port before calling play()");
}
return port;
}
public URL getUrl(String path) {
try {
return new URL("https://" + getHostName() + ":" + getPort() + path);
} catch (MalformedURLException e) {
throw new AssertionError(e);
}
}
/**
* Returns a cookie domain for this server. This returns the server's
* non-loopback host name if it is known. Otherwise this returns ".local"
* for this server's loopback name.
*/
public String getCookieDomain() {
String hostName = getHostName();
return hostName.contains(".") ? hostName : ".local";
}
/**
* Awaits the next HTTP request, removes it, and returns it. Callers should
* use this to verify the request sent was as intended.
*/
public RecordedRequest takeRequest() throws InterruptedException {
return requestQueue.take();
}
public void play() throws IOException {
serverSocket = new ServerSocket(0);
serverSocket.setReuseAddress(true);
port = serverSocket.getLocalPort();
Thread acceptThread = new Thread("MockSpdyServer-accept-" + port) {
@Override public void run() {
int sequenceNumber = 0;
try {
acceptConnections(sequenceNumber);
} catch (Throwable e) {
logger.log(Level.WARNING, "MockWebServer connection failed", e);
}
// This gnarly block of code will release all sockets and
// all thread, even if any close fails.
try {
serverSocket.close();
} catch (Throwable e) {
logger.log(Level.WARNING, "MockWebServer server socket close failed", e);
}
for (Iterator<Socket> s = openClientSockets.iterator(); s.hasNext(); ) {
try {
s.next().close();
s.remove();
} catch (Throwable e) {
logger.log(Level.WARNING, "MockWebServer socket close failed", e);
}
}
}
};
acceptThread.start();
}
public void enqueue(MockResponse response) {
dispatcher.enqueueResponse(response);
}
private void acceptConnections(int sequenceNumber) throws Exception {
while (true) {
Socket socket;
try {
socket = serverSocket.accept();
} catch (SocketException e) {
return;
}
openClientSockets.add(socket);
new SocketHandler(sequenceNumber++, socket).serve();
}
}
public void shutdown() throws IOException {
if (serverSocket != null) {
serverSocket.close(); // should cause acceptConnections() to break out
}
}
private class SocketHandler implements IncomingStreamHandler {
private final int sequenceNumber;
private Socket socket;
private SocketHandler(int sequenceNumber, Socket socket) throws IOException {
this.socket = socket;
this.sequenceNumber = sequenceNumber;
}
public void serve() throws IOException {
if (sslSocketFactory != null) {
socket = doSsl(socket);
}
new SpdyConnection.Builder(false, socket).handler(this).build();
}
private Socket doSsl(Socket socket) throws IOException {
SSLSocket sslSocket = (SSLSocket) sslSocketFactory.createSocket(socket,
socket.getInetAddress().getHostAddress(), socket.getPort(), true);
sslSocket.setUseClientMode(false);
Platform.get().setNpnProtocols(sslSocket, NPN_PROTOCOLS);
return sslSocket;
}
@Override public void receive(final SpdyStream stream) throws IOException {
RecordedRequest request = readRequest(stream);
requestQueue.add(request);
MockResponse response;
try {
response = dispatcher.dispatch(request);
} catch (InterruptedException e) {
throw new AssertionError(e);
}
writeResponse(stream, response);
logger.info("Received request: " + request + " and responded: " + response);
}
private RecordedRequest readRequest(SpdyStream stream) throws IOException {
List<String> spdyHeaders = stream.getRequestHeaders();
List<String> httpHeaders = new ArrayList<String>();
String method = "<:method omitted>";
String path = "<:path omitted>";
String version = "<:version omitted>";
for (Iterator<String> i = spdyHeaders.iterator(); i.hasNext(); ) {
String name = i.next();
String value = i.next();
if (":method".equals(name)) {
method = value;
} else if (":path".equals(name)) {
path = value;
} else if (":version".equals(name)) {
version = value;
} else {
httpHeaders.add(name + ": " + value);
}
}
InputStream bodyIn = stream.getInputStream();
ByteArrayOutputStream bodyOut = new ByteArrayOutputStream();
byte[] buffer = new byte[8192];
int count;
while ((count = bodyIn.read(buffer)) != -1) {
bodyOut.write(buffer, 0, count);
}
bodyIn.close();
String requestLine = method + ' ' + path + ' ' + version;
List<Integer> chunkSizes = Collections.emptyList(); // No chunked encoding for SPDY.
return new RecordedRequest(requestLine, httpHeaders, chunkSizes, bodyOut.size(),
bodyOut.toByteArray(), sequenceNumber, socket);
}
private void writeResponse(SpdyStream stream, MockResponse response) throws IOException {
List<String> spdyHeaders = new ArrayList<String>();
String[] statusParts = response.getStatus().split(" ", 2);
if (statusParts.length != 2) {
throw new AssertionError("Unexpected status: " + response.getStatus());
}
spdyHeaders.add(":status");
spdyHeaders.add(statusParts[1]);
spdyHeaders.add(":version");
spdyHeaders.add(statusParts[0]);
for (String header : response.getHeaders()) {
String[] headerParts = header.split(":", 2);
if (headerParts.length != 2) {
throw new AssertionError("Unexpected header: " + header);
}
spdyHeaders.add(headerParts[0].toLowerCase(Locale.US).trim());
spdyHeaders.add(headerParts[1].trim());
}
byte[] body = response.getBody();
stream.reply(spdyHeaders, body.length > 0);
if (body.length > 0) {
stream.getOutputStream().write(body);
stream.getOutputStream().close();
}
}
}
}

View File

@@ -16,8 +16,11 @@
package com.squareup.okhttp.mockwebserver;
import static com.squareup.okhttp.mockwebserver.SocketPolicy.DISCONNECT_AT_START;
import static com.squareup.okhttp.mockwebserver.SocketPolicy.FAIL_HANDSHAKE;
import com.squareup.okhttp.internal.Platform;
import com.squareup.okhttp.internal.Util;
import com.squareup.okhttp.internal.spdy.IncomingStreamHandler;
import com.squareup.okhttp.internal.spdy.SpdyConnection;
import com.squareup.okhttp.internal.spdy.SpdyStream;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
@@ -37,6 +40,8 @@ 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;
import java.util.Locale;
@@ -55,11 +60,24 @@ import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import static com.squareup.okhttp.mockwebserver.SocketPolicy.DISCONNECT_AT_START;
import static com.squareup.okhttp.mockwebserver.SocketPolicy.FAIL_HANDSHAKE;
/**
* A scriptable web server. Callers supply canned responses and the server
* replays them upon request in sequence.
*/
public final class MockWebServer {
private static final byte[] NPN_PROTOCOLS = {
6, 's', 'p', 'd', 'y', '/', '3',
8, 'h', 't', 't', 'p', '/', '1', '.', '1'
};
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'
};
static final String ASCII = "US-ASCII";
@@ -68,6 +86,8 @@ public final class MockWebServer {
= new LinkedBlockingQueue<RecordedRequest>();
/** All map values are Boolean.TRUE. (Collections.newSetFromMap isn't available in Froyo) */
private final Map<Socket, Boolean> openClientSockets = new ConcurrentHashMap<Socket, Boolean>();
private final Map<SpdyConnection, Boolean> openSpdyConnections
= new ConcurrentHashMap<SpdyConnection, Boolean>();
private final AtomicInteger requestCount = new AtomicInteger();
private int bodyLimit = Integer.MAX_VALUE;
private ServerSocket serverSocket;
@@ -77,6 +97,7 @@ public final class MockWebServer {
private Dispatcher dispatcher = new QueueDispatcher();
private int port = -1;
private boolean npnEnabled = true;
public int getPort() {
if (port == -1) {
@@ -130,6 +151,15 @@ public final class MockWebServer {
this.bodyLimit = maxBodyLength;
}
/**
* 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
* SPDY.
*/
public void setNpnEnabled(boolean npnEnabled) {
this.npnEnabled = npnEnabled;
}
/**
* Serve requests with HTTPS rather than otherwise.
*
@@ -219,6 +249,15 @@ public final class MockWebServer {
logger.log(Level.WARNING, "MockWebServer socket close failed", e);
}
}
for (Iterator<SpdyConnection> s = openSpdyConnections.keySet().iterator();
s.hasNext(); ) {
try {
s.next().close();
s.remove();
} catch (Throwable e) {
logger.log(Level.WARNING, "MockWebServer SPDY connection close failed", e);
}
}
try {
executor.shutdown();
} catch (Throwable e) {
@@ -267,6 +306,7 @@ public final class MockWebServer {
}
public void processConnection() throws Exception {
Transport transport = Transport.HTTP_11;
Socket socket;
if (sslSocketFactory != null) {
if (tunnelProxy) {
@@ -275,18 +315,47 @@ public final class MockWebServer {
final SocketPolicy socketPolicy = dispatcher.peekSocketPolicy();
if (socketPolicy == FAIL_HANDSHAKE) {
dispatchBookkeepingRequest(sequenceNumber, raw);
processHandshakeFailure(raw, sequenceNumber++);
processHandshakeFailure(raw);
return;
}
socket = sslSocketFactory.createSocket(
raw, raw.getInetAddress().getHostAddress(), raw.getPort(), true);
((SSLSocket) socket).setUseClientMode(false);
raw, raw.getInetAddress().getHostAddress(), raw.getPort(), true);
SSLSocket sslSocket = (SSLSocket) socket;
sslSocket.setUseClientMode(false);
openClientSockets.put(socket, true);
if (npnEnabled) {
Platform.get().setNpnProtocols(sslSocket, NPN_PROTOCOLS);
}
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, SPDY3)) {
transport = Transport.SPDY_3;
} else {
throw new IllegalStateException("Unexpected transport: "
+ new String(selectedProtocol, Util.US_ASCII));
}
}
openClientSockets.remove(raw);
} else {
socket = raw;
}
if (transport == Transport.SPDY_3) {
SpdySocketHandler spdySocketHandler = new SpdySocketHandler(socket);
SpdyConnection spdyConnection = new SpdyConnection.Builder(false, socket)
.handler(spdySocketHandler)
.build();
openSpdyConnections.put(spdyConnection, Boolean.TRUE);
openClientSockets.remove(socket);
return;
}
InputStream in = new BufferedInputStream(socket.getInputStream());
OutputStream out = new BufferedOutputStream(socket.getOutputStream());
@@ -348,7 +417,7 @@ public final class MockWebServer {
}));
}
private void processHandshakeFailure(Socket raw, int sequenceNumber) throws Exception {
private void processHandshakeFailure(Socket raw) throws Exception {
X509TrustManager untrusted = new X509TrustManager() {
@Override public void checkClientTrusted(X509Certificate[] chain, String authType)
throws CertificateException {
@@ -586,4 +655,90 @@ public final class MockWebServer {
}
};
}
/** Processes HTTP requests layered over SPDY/3. */
private class SpdySocketHandler implements IncomingStreamHandler {
private final Socket socket;
private SpdySocketHandler(Socket socket) {
this.socket = socket;
}
@Override public void receive(final SpdyStream stream) throws IOException {
RecordedRequest request = readRequest(stream);
requestQueue.add(request);
MockResponse response;
try {
response = dispatcher.dispatch(request);
} catch (InterruptedException e) {
throw new AssertionError(e);
}
writeResponse(stream, response);
logger.info("Received request: " + request + " and responded: " + response);
}
private RecordedRequest readRequest(SpdyStream stream) throws IOException {
List<String> spdyHeaders = stream.getRequestHeaders();
List<String> httpHeaders = new ArrayList<String>();
String method = "<:method omitted>";
String path = "<:path omitted>";
String version = "<:version omitted>";
for (Iterator<String> i = spdyHeaders.iterator(); i.hasNext(); ) {
String name = i.next();
String value = i.next();
if (":method".equals(name)) {
method = value;
} else if (":path".equals(name)) {
path = value;
} else if (":version".equals(name)) {
version = value;
} else {
httpHeaders.add(name + ": " + value);
}
}
InputStream bodyIn = stream.getInputStream();
ByteArrayOutputStream bodyOut = new ByteArrayOutputStream();
byte[] buffer = new byte[8192];
int count;
while ((count = bodyIn.read(buffer)) != -1) {
bodyOut.write(buffer, 0, count);
}
bodyIn.close();
String requestLine = method + ' ' + path + ' ' + version;
List<Integer> chunkSizes = Collections.emptyList(); // No chunked encoding for SPDY.
return new RecordedRequest(requestLine, httpHeaders, chunkSizes, bodyOut.size(),
bodyOut.toByteArray(), 0, socket);
}
private void writeResponse(SpdyStream stream, MockResponse response) throws IOException {
List<String> spdyHeaders = new ArrayList<String>();
String[] statusParts = response.getStatus().split(" ", 2);
if (statusParts.length != 2) {
throw new AssertionError("Unexpected status: " + response.getStatus());
}
spdyHeaders.add(":status");
spdyHeaders.add(statusParts[1]);
spdyHeaders.add(":version");
spdyHeaders.add(statusParts[0]);
for (String header : response.getHeaders()) {
String[] headerParts = header.split(":", 2);
if (headerParts.length != 2) {
throw new AssertionError("Unexpected header: " + header);
}
spdyHeaders.add(headerParts[0].toLowerCase(Locale.US).trim());
spdyHeaders.add(headerParts[1].trim());
}
byte[] body = response.getBody();
stream.reply(spdyHeaders, body.length > 0);
if (body.length > 0) {
stream.getOutputStream().write(body);
stream.getOutputStream().close();
}
}
}
enum Transport {
HTTP_11, SPDY_3
}
}

View File

@@ -79,11 +79,11 @@ abstract class AbstractHttpInputStream extends InputStream {
* Closes the cache entry and makes the socket available for reuse. This
* should be invoked when the end of the body has been reached.
*/
protected final void endOfInput(boolean streamCancelled) throws IOException {
protected final void endOfInput() throws IOException {
if (cacheRequest != null) {
cacheBody.close();
}
httpEngine.release(streamCancelled);
httpEngine.release(false);
}
/**

View File

@@ -426,7 +426,7 @@ public class HttpEngine {
* closed. Also call {@link #automaticallyReleaseConnectionToPool} unless
* the connection will be used to follow a redirect.
*/
public final void release(boolean streamCancelled) {
public final void release(boolean streamCanceled) {
// If the response body comes from the cache, close it.
if (responseBodyIn == cachedResponseBody) {
Util.closeQuietly(responseBodyIn);
@@ -435,8 +435,8 @@ public class HttpEngine {
if (!connectionReleased && connection != null) {
connectionReleased = true;
if (transport == null || !transport.makeReusable(streamCancelled, requestBodyOut,
responseTransferIn)) {
if (transport == null
|| !transport.makeReusable(streamCanceled, requestBodyOut, responseTransferIn)) {
Util.closeQuietly(connection);
connection = null;
} else if (automaticallyReleaseConnectionToPool) {

View File

@@ -141,9 +141,9 @@ public final class HttpTransport implements Transport {
return headers;
}
public boolean makeReusable(boolean streamCancelled, OutputStream requestBodyOut,
public boolean makeReusable(boolean streamCanceled, OutputStream requestBodyOut,
InputStream responseBodyIn) {
if (streamCancelled) {
if (streamCanceled) {
return false;
}
@@ -177,6 +177,10 @@ public final class HttpTransport implements Transport {
* Discards the response body so that the connection can be reused. This
* needs to be done judiciously, since it delays the current request in
* order to speed up a potential future request that may never occur.
*
* <p>A stream may be discarded to encourage response caching (a response
* cannot be cached unless it is consumed completely) or to enable connection
* reuse.
*/
private static boolean discardStream(HttpEngine httpEngine, InputStream responseBodyIn) {
Connection connection = httpEngine.connection;
@@ -373,7 +377,7 @@ public final class HttpTransport implements Transport {
super(is, httpEngine, cacheRequest);
bytesRemaining = length;
if (bytesRemaining == 0) {
endOfInput(false);
endOfInput();
}
}
@@ -391,7 +395,7 @@ public final class HttpTransport implements Transport {
bytesRemaining -= read;
cacheWrite(buffer, offset, read);
if (bytesRemaining == 0) {
endOfInput(false);
endOfInput();
}
return read;
}
@@ -468,7 +472,7 @@ public final class HttpTransport implements Transport {
RawHeaders rawResponseHeaders = httpEngine.responseHeaders.getHeaders();
RawHeaders.readHeaders(transport.socketIn, rawResponseHeaders);
httpEngine.receiveHeaders(rawResponseHeaders);
endOfInput(false);
endOfInput();
}
}

View File

@@ -80,15 +80,15 @@ public final class SpdyTransport implements Transport {
return new UnknownLengthHttpInputStream(stream.getInputStream(), cacheRequest, httpEngine);
}
@Override public boolean makeReusable(boolean streamCancelled, OutputStream requestBodyOut,
@Override public boolean makeReusable(boolean streamCanceled, OutputStream requestBodyOut,
InputStream responseBodyIn) {
if (streamCancelled) {
if (streamCanceled) {
if (stream != null) {
stream.closeLater(SpdyStream.RST_CANCEL);
return true;
} else {
// If stream is null, it either means that writeRequestHeaders wasn't called
// or that SpdyConnection#newStream threw an IOEXception. In both cases there's
// or that SpdyConnection#newStream threw an IOException. In both cases there's
// nothing to do here and this stream can't be reused.
return false;
}

View File

@@ -59,6 +59,6 @@ interface Transport {
InputStream getTransferStream(CacheRequest cacheRequest) throws IOException;
/** Returns true if the underlying connection can be recycled. */
boolean makeReusable(boolean streamReusable, OutputStream requestBodyOut,
boolean makeReusable(boolean streamCanceled, OutputStream requestBodyOut,
InputStream responseBodyIn);
}

View File

@@ -25,9 +25,9 @@ import static com.squareup.okhttp.internal.Util.checkOffsetAndCount;
final class UnknownLengthHttpInputStream extends AbstractHttpInputStream {
private boolean inputExhausted;
UnknownLengthHttpInputStream(InputStream is, CacheRequest cacheRequest, HttpEngine httpEngine)
UnknownLengthHttpInputStream(InputStream in, CacheRequest cacheRequest, HttpEngine httpEngine)
throws IOException {
super(is, httpEngine, cacheRequest);
super(in, httpEngine, cacheRequest);
}
@Override public int read(byte[] buffer, int offset, int count) throws IOException {
@@ -39,7 +39,7 @@ final class UnknownLengthHttpInputStream extends AbstractHttpInputStream {
int read = in.read(buffer, offset, count);
if (read == -1) {
inputExhausted = true;
endOfInput(false);
endOfInput();
return -1;
}
cacheWrite(buffer, offset, read);

View File

@@ -15,12 +15,11 @@
*/
package com.squareup.okhttp;
import com.squareup.okhttp.mockwebserver.MockWebServer;
import com.squareup.okhttp.internal.RecordingHostnameVerifier;
import com.squareup.okhttp.internal.SslContextBuilder;
import com.squareup.okhttp.internal.Util;
import com.squareup.okhttp.internal.http.HttpAuthenticator;
import com.squareup.okhttp.internal.mockspdyserver.MockSpdyServer;
import com.squareup.okhttp.mockwebserver.MockWebServer;
import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
@@ -53,7 +52,7 @@ public final class ConnectionPoolTest {
}
}
private final MockSpdyServer spdyServer = new MockSpdyServer(sslContext.getSocketFactory());
private final MockWebServer spdyServer = new MockWebServer();
private InetSocketAddress spdySocketAddress;
private Address spdyAddress;
@@ -70,6 +69,8 @@ public final class ConnectionPoolTest {
private Connection spdyB;
@Before public void setUp() throws Exception {
spdyServer.useHttps(sslContext.getSocketFactory(), false);
httpServer.play();
httpAddress = new Address(httpServer.getHostName(), httpServer.getPort(), null, null,
HttpAuthenticator.SYSTEM_DEFAULT, null, Arrays.asList("spdy/3", "http/1.1"));

View File

@@ -15,14 +15,14 @@
*/
package com.squareup.okhttp.internal.http;
import com.squareup.okhttp.mockwebserver.MockResponse;
import com.squareup.okhttp.mockwebserver.RecordedRequest;
import com.squareup.okhttp.HttpResponseCache;
import com.squareup.okhttp.OkHttpClient;
import com.squareup.okhttp.internal.RecordingAuthenticator;
import com.squareup.okhttp.internal.SslContextBuilder;
import com.squareup.okhttp.internal.Util;
import com.squareup.okhttp.internal.mockspdyserver.MockSpdyServer;
import com.squareup.okhttp.mockwebserver.MockResponse;
import com.squareup.okhttp.mockwebserver.MockWebServer;
import com.squareup.okhttp.mockwebserver.RecordedRequest;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
@@ -72,12 +72,13 @@ public final class HttpOverSpdyTest {
throw new RuntimeException(e);
}
}
private final MockSpdyServer server = new MockSpdyServer(sslContext.getSocketFactory());
private final MockWebServer server = new MockWebServer();
private final String hostName = server.getHostName();
private final OkHttpClient client = new OkHttpClient();
private HttpResponseCache cache;
@Before public void setUp() throws Exception {
server.useHttps(sslContext.getSocketFactory(), false);
client.setSslSocketFactory(sslContext.getSocketFactory());
client.setHostnameVerifier(NULL_HOSTNAME_VERIFIER);
String systemTmpDir = System.getProperty("java.io.tmpdir");

View File

@@ -16,13 +16,13 @@
package com.squareup.okhttp.internal.http;
import com.squareup.okhttp.mockwebserver.MockResponse;
import com.squareup.okhttp.mockwebserver.MockWebServer;
import com.squareup.okhttp.mockwebserver.RecordedRequest;
import com.squareup.okhttp.HttpResponseCache;
import com.squareup.okhttp.OkHttpClient;
import com.squareup.okhttp.ResponseSource;
import com.squareup.okhttp.internal.SslContextBuilder;
import com.squareup.okhttp.mockwebserver.MockResponse;
import com.squareup.okhttp.mockwebserver.MockWebServer;
import com.squareup.okhttp.mockwebserver.RecordedRequest;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.File;
@@ -110,6 +110,7 @@ public final class HttpResponseCacheTest {
cache = new HttpResponseCache(cacheDir, Integer.MAX_VALUE);
ResponseCache.setDefault(cache);
CookieHandler.setDefault(cookieManager);
server.setNpnEnabled(false);
}
@After public void tearDown() throws Exception {
@@ -437,15 +438,14 @@ public final class HttpResponseCacheTest {
server.enqueue(new MockResponse().setBody("DEF"));
server.play();
client.setSslSocketFactory(sslContext.getSocketFactory());
client.setHostnameVerifier(NULL_HOSTNAME_VERIFIER);
HttpsURLConnection connection1 = (HttpsURLConnection) client.open(server.getUrl("/"));
connection1.setSSLSocketFactory(sslContext.getSocketFactory());
connection1.setHostnameVerifier(NULL_HOSTNAME_VERIFIER);
assertEquals("ABC", readAscii(connection1));
// Cached!
HttpsURLConnection connection2 = (HttpsURLConnection) client.open(server.getUrl("/"));
connection1.setSSLSocketFactory(sslContext.getSocketFactory());
connection1.setHostnameVerifier(NULL_HOSTNAME_VERIFIER);
assertEquals("ABC", readAscii(connection2));
assertEquals(4, cache.getRequestCount()); // 2 direct + 2 redirect = 4

View File

@@ -109,6 +109,7 @@ public final class URLConnectionTest {
@Before public void setUp() throws Exception {
hostName = server.getHostName();
server.setNpnEnabled(false);
}
@After public void tearDown() throws Exception {
@@ -1619,6 +1620,7 @@ public final class URLConnectionTest {
if (https) {
server.useHttps(sslContext.getSocketFactory(), false);
server2.useHttps(sslContext.getSocketFactory(), false);
server2.setNpnEnabled(false);
client.setSslSocketFactory(sslContext.getSocketFactory());
client.setHostnameVerifier(new RecordingHostnameVerifier());
}