summaryrefslogtreecommitdiffstats
path: root/luni
diff options
context:
space:
mode:
authorNeil Fuller <nfuller@google.com>2014-02-20 09:49:05 +0000
committerGerrit Code Review <noreply-gerritcodereview@google.com>2014-02-20 09:49:05 +0000
commit6d9b21a13ad3e8c2fb82427b1ddb967668425467 (patch)
treef017d9dc4201ad736d91f90dfa38bede9b12f060 /luni
parent01252476ca9d5a432e6b69c80284e50f40ce6b22 (diff)
parent76fafa7b18ae7e977fabb64742fd3c1449ee0f57 (diff)
downloadlibcore-6d9b21a13ad3e8c2fb82427b1ddb967668425467.zip
libcore-6d9b21a13ad3e8c2fb82427b1ddb967668425467.tar.gz
libcore-6d9b21a13ad3e8c2fb82427b1ddb967668425467.tar.bz2
Merge "Change HttpsURLConnectionTest for okhttp update."
Diffstat (limited to 'luni')
-rw-r--r--luni/src/test/java/org/apache/harmony/luni/tests/internal/net/www/protocol/https/HttpsURLConnectionTest.java1043
1 files changed, 467 insertions, 576 deletions
diff --git a/luni/src/test/java/org/apache/harmony/luni/tests/internal/net/www/protocol/https/HttpsURLConnectionTest.java b/luni/src/test/java/org/apache/harmony/luni/tests/internal/net/www/protocol/https/HttpsURLConnectionTest.java
index c516f67..5258fd1 100644
--- a/luni/src/test/java/org/apache/harmony/luni/tests/internal/net/www/protocol/https/HttpsURLConnectionTest.java
+++ b/luni/src/test/java/org/apache/harmony/luni/tests/internal/net/www/protocol/https/HttpsURLConnectionTest.java
@@ -17,6 +17,12 @@
package org.apache.harmony.luni.tests.internal.net.www.protocol.https;
+import com.google.mockwebserver.Dispatcher;
+import com.google.mockwebserver.MockResponse;
+import com.google.mockwebserver.MockWebServer;
+import com.google.mockwebserver.RecordedRequest;
+import com.google.mockwebserver.SocketPolicy;
+
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
@@ -25,7 +31,6 @@ import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
-import java.io.PrintStream;
import java.net.Authenticator;
import java.net.InetSocketAddress;
import java.net.PasswordAuthentication;
@@ -36,20 +41,15 @@ import java.net.URL;
import java.security.KeyStore;
import java.security.cert.Certificate;
import java.util.Arrays;
-import java.util.concurrent.Callable;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.Future;
-import java.util.concurrent.TimeUnit;
+import java.util.Collections;
+import java.util.LinkedList;
+
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
-import javax.net.ssl.SSLServerSocket;
import javax.net.ssl.SSLSession;
-import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
@@ -59,22 +59,26 @@ import libcore.javax.net.ssl.TestTrustManager;
/**
* Implementation independent test for HttpsURLConnection.
- * The test needs certstore file placed in system classpath
- * and named as "key_store." + the type of the
- * default KeyStore installed in the system in lower case.
- * <br>
- * For example: if default KeyStore type in the system is BKS
- * (i.e. java.security file sets up the property keystore.type=BKS),
- * thus classpath should point to the directory with "key_store.bks"
- * file.
- * <br>
- * This certstore file should contain self-signed certificate
- * generated by keytool utility in a usual way.
- * <br>
- * The password to the certstore should be "password" (without quotes).
*/
public class HttpsURLConnectionTest extends TestCase {
+ private static final String POST_METHOD = "POST";
+
+ private static final String GET_METHOD = "GET";
+
+ /**
+ * Data to be posted by client to the server when the method is POST.
+ */
+ private static final String POST_DATA = "_.-^ Client's Data ^-._";
+
+ /**
+ * The content of the response to be sent during HTTPS session.
+ */
+ private static final String RESPONSE_CONTENT
+ = "<HTML>\n"
+ + "<HEAD><TITLE>HTTPS Response Content</TITLE></HEAD>\n"
+ + "</HTML>";
+
// the password to the store
private static final String KS_PASSWORD = "password";
@@ -107,7 +111,7 @@ public class HttpsURLConnectionTest extends TestCase {
* Checks that HttpsURLConnection's default SSLSocketFactory is operable.
*/
public void testGetDefaultSSLSocketFactory() throws Exception {
- // set up the properties defining the default values needed by SSL stuff
+ // set up the properties pointing to the key/trust stores
setUpStoreProperties();
SSLSocketFactory defaultSSLSF = HttpsURLConnection.getDefaultSSLSocketFactory();
@@ -119,55 +123,58 @@ public class HttpsURLConnectionTest extends TestCase {
}
public void testHttpsConnection() throws Throwable {
- // set up the properties defining the default values needed by SSL stuff
+ // set up the properties pointing to the key/trust stores
setUpStoreProperties();
- // create the SSL server socket acting as a server
SSLContext ctx = getContext();
- ServerSocket ss = ctx.getServerSocketFactory().createServerSocket(0);
- // create the HostnameVerifier to check hostname verification
- TestHostnameVerifier hnv = new TestHostnameVerifier();
- HttpsURLConnection.setDefaultHostnameVerifier(hnv);
+ // set the HostnameVerifier required to satisfy SSL - always returns "verified".
+ HttpsURLConnection.setDefaultHostnameVerifier(new TestHostnameVerifier());
+
+ // create a webserver to check and respond to requests
+ SingleRequestDispatcher dispatcher = new SingleRequestDispatcher(GET_METHOD, OK_CODE);
+ MockWebServer webServer = createWebServer(ctx, dispatcher);
// create url connection to be tested
- URL url = new URL("https://localhost:" + ss.getLocalPort());
+ URL url = webServer.getUrl("/");
HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
connection.setSSLSocketFactory(ctx.getSocketFactory());
// perform the interaction between the peers
- SSLSocket peerSocket = (SSLSocket) doInteraction(connection, ss);
+ executeClientRequest(connection, false /* doOutput */);
- // check the connection state
- checkConnectionStateParameters(connection, peerSocket);
+ checkConnectionStateParameters(connection, dispatcher.getLastRequest());
// should silently exit
connection.connect();
+
+ webServer.shutdown();
}
/**
- * Tests the behaviour of HTTPS connection in case of unavailability
- * of requested resource.
+ * Tests the behaviour of HTTPS connection in case of unavailability of requested resource.
*/
public void testHttpsConnection_Not_Found_Response() throws Throwable {
- // set up the properties defining the default values needed by SSL stuff
+ // set up the properties pointing to the key/trust stores
setUpStoreProperties();
- // create the SSL server socket acting as a server
SSLContext ctx = getContext();
- ServerSocket ss = ctx.getServerSocketFactory().createServerSocket(0);
- // create the HostnameVerifier to check hostname verification
- TestHostnameVerifier hnv = new TestHostnameVerifier();
- HttpsURLConnection.setDefaultHostnameVerifier(hnv);
+ // set the HostnameVerifier required to satisfy SSL - always returns "verified".
+ HttpsURLConnection.setDefaultHostnameVerifier(new TestHostnameVerifier());
+
+ // create a webserver to check and respond to requests
+ SingleRequestDispatcher dispatcher =
+ new SingleRequestDispatcher(GET_METHOD, NOT_FOUND_CODE);
+ MockWebServer webServer = createWebServer(ctx, dispatcher);
// create url connection to be tested
- URL url = new URL("https://localhost:" + ss.getLocalPort());
+ URL url = webServer.getUrl("/");
HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
connection.setSSLSocketFactory(ctx.getSocketFactory());
try {
- doInteraction(connection, ss, NOT_FOUND_CODE);
+ executeClientRequest(connection, false /* doOutput */);
fail("Expected exception was not thrown.");
} catch (FileNotFoundException e) {
if (DO_LOG) {
@@ -178,94 +185,100 @@ public class HttpsURLConnectionTest extends TestCase {
// should silently exit
connection.connect();
+
+ webServer.shutdown();
}
/**
- * Tests possibility to set up the default SSLSocketFactory
- * to be used by HttpsURLConnection.
+ * Tests possibility to set up the default SSLSocketFactory to be used by HttpsURLConnection.
*/
public void testSetDefaultSSLSocketFactory() throws Throwable {
- // create the SSLServerSocket which will be used by server side
+ // set up the properties pointing to the key/trust stores
+ setUpStoreProperties();
+
SSLContext ctx = getContext();
- SSLServerSocket ss = (SSLServerSocket) ctx.getServerSocketFactory().createServerSocket(0);
- SSLSocketFactory socketFactory = (SSLSocketFactory) ctx.getSocketFactory();
+ SSLSocketFactory socketFactory = ctx.getSocketFactory();
// set up the factory as default
HttpsURLConnection.setDefaultSSLSocketFactory(socketFactory);
// check the result
assertSame("Default SSLSocketFactory differs from expected",
- socketFactory, HttpsURLConnection.getDefaultSSLSocketFactory());
+ socketFactory, HttpsURLConnection.getDefaultSSLSocketFactory());
- // create the HostnameVerifier to check hostname verification
- TestHostnameVerifier hnv = new TestHostnameVerifier();
- HttpsURLConnection.setDefaultHostnameVerifier(hnv);
+ // set the initial default host name verifier.
+ TestHostnameVerifier initialHostnameVerifier = new TestHostnameVerifier();
+ HttpsURLConnection.setDefaultHostnameVerifier(initialHostnameVerifier);
+
+ // create a webserver to check and respond to requests
+ SingleRequestDispatcher dispatcher = new SingleRequestDispatcher(GET_METHOD, OK_CODE);
+ MockWebServer webServer = createWebServer(ctx, dispatcher);
// create HttpsURLConnection to be tested
- URL url = new URL("https://localhost:" + ss.getLocalPort());
+ URL url = webServer.getUrl("/");
HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
- TestHostnameVerifier hnv_late = new TestHostnameVerifier();
- // late initialization: should not be used for created connection
- HttpsURLConnection.setDefaultHostnameVerifier(hnv_late);
+ // late initialization: this HostnameVerifier should not be used for created connection
+ TestHostnameVerifier lateHostnameVerifier = new TestHostnameVerifier();
+ HttpsURLConnection.setDefaultHostnameVerifier(lateHostnameVerifier);
// perform the interaction between the peers
- SSLSocket peerSocket = (SSLSocket) doInteraction(connection, ss);
- // check the connection state
- checkConnectionStateParameters(connection, peerSocket);
+ executeClientRequest(connection, false /* doOutput */);
+ checkConnectionStateParameters(connection, dispatcher.getLastRequest());
+
// check the verification process
- assertTrue("Hostname verification was not done", hnv.verified);
+ assertTrue("Hostname verification was not done", initialHostnameVerifier.verified);
assertFalse("Hostname verification should not be done by this verifier",
- hnv_late.verified);
+ lateHostnameVerifier.verified);
// check the used SSLSocketFactory
assertSame("Default SSLSocketFactory should be used",
- HttpsURLConnection.getDefaultSSLSocketFactory(),
- connection.getSSLSocketFactory());
+ HttpsURLConnection.getDefaultSSLSocketFactory(),
+ connection.getSSLSocketFactory());
- // should silently exit
- connection.connect();
+ webServer.shutdown();
}
/**
- * Tests possibility to set up the SSLSocketFactory
- * to be used by HttpsURLConnection.
+ * Tests
+ * {@link javax.net.ssl.HttpsURLConnection#setSSLSocketFactory(javax.net.ssl.SSLSocketFactory)}.
*/
public void testSetSSLSocketFactory() throws Throwable {
- // create the SSLServerSocket which will be used by server side
+ // set up the properties pointing to the key/trust stores
SSLContext ctx = getContext();
- SSLServerSocket ss = (SSLServerSocket) ctx.getServerSocketFactory().createServerSocket(0);
- // create the HostnameVerifier to check hostname verification
- TestHostnameVerifier hnv = new TestHostnameVerifier();
- HttpsURLConnection.setDefaultHostnameVerifier(hnv);
+ // set the initial default host name verifier.
+ TestHostnameVerifier hostnameVerifier = new TestHostnameVerifier();
+ HttpsURLConnection.setDefaultHostnameVerifier(hostnameVerifier);
+
+ // create a webserver to check and respond to requests
+ SingleRequestDispatcher dispatcher = new SingleRequestDispatcher(GET_METHOD, OK_CODE);
+ MockWebServer webServer = createWebServer(ctx, dispatcher);
// create HttpsURLConnection to be tested
- URL url = new URL("https://localhost:" + ss.getLocalPort());
+ URL url = webServer.getUrl("/");
HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
- SSLSocketFactory socketFactory = (SSLSocketFactory) ctx.getSocketFactory();
+ // late initialization: should not be used for the created connection.
+ SSLSocketFactory socketFactory = ctx.getSocketFactory();
connection.setSSLSocketFactory(socketFactory);
- TestHostnameVerifier hnv_late = new TestHostnameVerifier();
// late initialization: should not be used for created connection
- HttpsURLConnection.setDefaultHostnameVerifier(hnv_late);
+ TestHostnameVerifier lateHostnameVerifier = new TestHostnameVerifier();
+ HttpsURLConnection.setDefaultHostnameVerifier(lateHostnameVerifier);
// perform the interaction between the peers
- SSLSocket peerSocket = (SSLSocket) doInteraction(connection, ss);
- // check the connection state
- checkConnectionStateParameters(connection, peerSocket);
+ executeClientRequest(connection, false /* doOutput */);
+ checkConnectionStateParameters(connection, dispatcher.getLastRequest());
// check the verification process
- assertTrue("Hostname verification was not done", hnv.verified);
+ assertTrue("Hostname verification was not done", hostnameVerifier.verified);
assertFalse("Hostname verification should not be done by this verifier",
- hnv_late.verified);
+ lateHostnameVerifier.verified);
// check the used SSLSocketFactory
assertNotSame("Default SSLSocketFactory should not be used",
- HttpsURLConnection.getDefaultSSLSocketFactory(),
- connection.getSSLSocketFactory());
- assertSame("Result differs from expected",
- socketFactory, connection.getSSLSocketFactory());
+ HttpsURLConnection.getDefaultSSLSocketFactory(),
+ connection.getSSLSocketFactory());
+ assertSame("Result differs from expected", socketFactory, connection.getSSLSocketFactory());
- // should silently exit
- connection.connect();
+ webServer.shutdown();
}
/**
@@ -304,97 +317,107 @@ public class HttpsURLConnectionTest extends TestCase {
* Tests if setHostnameVerifier() method replaces default verifier.
*/
public void testSetHostnameVerifier() throws Throwable {
- // setting up the properties pointing to the key/trust stores
+ // set up the properties pointing to the key/trust stores
setUpStoreProperties();
- // create the SSLServerSocket which will be used by server side
- SSLServerSocket ss = (SSLServerSocket)
- getContext().getServerSocketFactory().createServerSocket(0);
+ SSLContext ctx = getContext();
+
+ TestHostnameVerifier defaultHostnameVerifier = new TestHostnameVerifier();
+ HttpsURLConnection.setDefaultHostnameVerifier(defaultHostnameVerifier);
- // create the HostnameVerifier to check that Hostname verification
- // is done
- TestHostnameVerifier hnv = new TestHostnameVerifier();
- HttpsURLConnection.setDefaultHostnameVerifier(hnv);
+ // create a webserver to check and respond to requests
+ SingleRequestDispatcher dispatcher = new SingleRequestDispatcher(GET_METHOD, OK_CODE);
+ MockWebServer webServer = createWebServer(ctx, dispatcher);
// create HttpsURLConnection to be tested
- URL url = new URL("https://localhost:" + ss.getLocalPort());
+ URL url = webServer.getUrl("/");
HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
connection.setSSLSocketFactory(getContext().getSocketFactory());
- TestHostnameVerifier hnv_late = new TestHostnameVerifier();
- // replace default verifier
- connection.setHostnameVerifier(hnv_late);
+ // replace the default verifier
+ TestHostnameVerifier connectionHostnameVerifier = new TestHostnameVerifier();
+ connection.setHostnameVerifier(connectionHostnameVerifier);
// perform the interaction between the peers and check the results
- SSLSocket peerSocket = (SSLSocket) doInteraction(connection, ss);
- assertTrue("Hostname verification was not done", hnv_late.verified);
+ executeClientRequest(connection, false /* doOutput */);
+ assertTrue("Hostname verification was not done", connectionHostnameVerifier.verified);
assertFalse("Hostname verification should not be done by this verifier",
- hnv.verified);
- checkConnectionStateParameters(connection, peerSocket);
+ defaultHostnameVerifier.verified);
- // should silently exit
- connection.connect();
+ checkConnectionStateParameters(connection, dispatcher.getLastRequest());
+
+ webServer.shutdown();
}
/**
* Tests the behaviour in case of sending the data to the server.
*/
public void test_doOutput() throws Throwable {
- // setting up the properties pointing to the key/trust stores
+ // set up the properties pointing to the key/trust stores
setUpStoreProperties();
- // create the SSLServerSocket which will be used by server side
- SSLServerSocket ss = (SSLServerSocket)
- getContext().getServerSocketFactory().createServerSocket(0);
+ SSLContext ctx = getContext();
- // create the HostnameVerifier to check that Hostname verification
- // is done
- TestHostnameVerifier hnv = new TestHostnameVerifier();
- HttpsURLConnection.setDefaultHostnameVerifier(hnv);
+ // create a webserver to check and respond to requests
+ SingleRequestDispatcher dispatcher = new SingleRequestDispatcher(POST_METHOD, OK_CODE);
+ MockWebServer webServer = createWebServer(ctx, dispatcher);
+
+ // set the HostnameVerifier required to satisfy SSL - always returns "verified".
+ HttpsURLConnection.setDefaultHostnameVerifier(new TestHostnameVerifier());
// create HttpsURLConnection to be tested
- URL url = new URL("https://localhost:" + ss.getLocalPort());
+ URL url = webServer.getUrl("/");
HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
connection.setSSLSocketFactory(getContext().getSocketFactory());
- connection.setDoOutput(true);
// perform the interaction between the peers and check the results
- SSLSocket peerSocket = (SSLSocket) doInteraction(connection, ss);
- checkConnectionStateParameters(connection, peerSocket);
+ executeClientRequest(connection, true /* doOutput */);
+ checkConnectionStateParameters(connection, dispatcher.getLastRequest());
// should silently exit
connection.connect();
+
+ webServer.shutdown();
}
/**
* Tests HTTPS connection process made through the proxy server.
*/
public void testProxyConnection() throws Throwable {
- // setting up the properties pointing to the key/trust stores
+ // set up the properties pointing to the key/trust stores
setUpStoreProperties();
- // create the SSLServerSocket which will be used by server side
- ServerSocket ss = new ServerSocket(0);
+ SSLContext ctx = getContext();
- // create the HostnameVerifier to check that Hostname verification
- // is done
- TestHostnameVerifier hnv = new TestHostnameVerifier();
- HttpsURLConnection.setDefaultHostnameVerifier(hnv);
+ // set the HostnameVerifier required to satisfy SSL - always returns "verified".
+ HttpsURLConnection.setDefaultHostnameVerifier(new TestHostnameVerifier());
+
+ // create a server that pretends to be both a proxy and then the webserver
+ // request 1: proxy CONNECT, respond with OK
+ ProxyConnectDispatcher proxyConnectDispatcher =
+ new ProxyConnectDispatcher(false /* authenticationRequired */);
+ // request 2: tunnelled GET, respond with OK
+ SingleRequestDispatcher getDispatcher = new SingleRequestDispatcher(GET_METHOD, OK_CODE);
+ DelegatingDispatcher delegatingDispatcher =
+ new DelegatingDispatcher(proxyConnectDispatcher, getDispatcher);
+ MockWebServer proxyAndWebServer = createProxyAndWebServer(ctx, delegatingDispatcher);
// create HttpsURLConnection to be tested
+ URL proxyUrl = proxyAndWebServer.getUrl("/");
+ InetSocketAddress proxyAddress = new InetSocketAddress("localhost", proxyUrl.getPort());
URL url = new URL("https://requested.host:55556/requested.data");
HttpsURLConnection connection = (HttpsURLConnection)
- url.openConnection(new Proxy(Proxy.Type.HTTP,
- new InetSocketAddress("localhost",
- ss.getLocalPort())));
+ url.openConnection(new Proxy(Proxy.Type.HTTP, proxyAddress));
connection.setSSLSocketFactory(getContext().getSocketFactory());
// perform the interaction between the peers and check the results
- SSLSocket peerSocket = (SSLSocket) doInteraction(connection, ss);
- checkConnectionStateParameters(connection, peerSocket);
+ executeClientRequest(connection, false /* doOutput */);
+ checkConnectionStateParameters(connection, getDispatcher.getLastRequest());
// should silently exit
connection.connect();
+
+ proxyAndWebServer.shutdown();
}
/**
@@ -402,81 +425,105 @@ public class HttpsURLConnectionTest extends TestCase {
* Proxy server needs authentication.
*/
public void testProxyAuthConnection() throws Throwable {
- // setting up the properties pointing to the key/trust stores
+ // set up the properties pointing to the key/trust stores
setUpStoreProperties();
- // create the SSLServerSocket which will be used by server side
- ServerSocket ss = new ServerSocket(0);
+ SSLContext ctx = getContext();
- // create the HostnameVerifier to check that Hostname verification
- // is done
- TestHostnameVerifier hnv = new TestHostnameVerifier();
- HttpsURLConnection.setDefaultHostnameVerifier(hnv);
+ // set the HostnameVerifier required to satisfy SSL - always returns "verified".
+ HttpsURLConnection.setDefaultHostnameVerifier(new TestHostnameVerifier());
Authenticator.setDefault(new Authenticator() {
-
protected PasswordAuthentication getPasswordAuthentication() {
- return new PasswordAuthentication("user", "password"
- .toCharArray());
+ return new PasswordAuthentication("user", "password".toCharArray());
}
});
+ // create a server that pretends to be both a proxy and then the webserver
+ // request 1: proxy CONNECT, respond with auth challenge
+ ProxyConnectAuthFailDispatcher authFailDispatcher = new ProxyConnectAuthFailDispatcher();
+ // request 2: proxy CONNECT, respond with OK
+ ProxyConnectDispatcher proxyConnectDispatcher =
+ new ProxyConnectDispatcher(true /* authenticationRequired */);
+ // request 3: tunnelled GET, respond with OK
+ SingleRequestDispatcher getDispatcher = new SingleRequestDispatcher(GET_METHOD, OK_CODE);
+ DelegatingDispatcher delegatingDispatcher = new DelegatingDispatcher(
+ authFailDispatcher, proxyConnectDispatcher, getDispatcher);
+ MockWebServer proxyAndWebServer = createProxyAndWebServer(ctx, delegatingDispatcher);
+
// create HttpsURLConnection to be tested
+ URL proxyUrl = proxyAndWebServer.getUrl("/");
+ InetSocketAddress proxyAddress = new InetSocketAddress("localhost", proxyUrl.getPort());
URL url = new URL("https://requested.host:55555/requested.data");
HttpsURLConnection connection = (HttpsURLConnection)
- url.openConnection(new Proxy(Proxy.Type.HTTP,
- new InetSocketAddress("localhost",
- ss.getLocalPort())));
+ url.openConnection(new Proxy(Proxy.Type.HTTP, proxyAddress));
connection.setSSLSocketFactory(getContext().getSocketFactory());
// perform the interaction between the peers and check the results
- SSLSocket peerSocket = (SSLSocket) doInteraction(connection, ss);
- checkConnectionStateParameters(connection, peerSocket);
+ executeClientRequest(connection, false /* doOutput */);
+ checkConnectionStateParameters(connection, getDispatcher.getLastRequest());
// should silently exit
connection.connect();
+
+ proxyAndWebServer.shutdown();
}
/**
* Tests HTTPS connection process made through the proxy server.
- * 2 HTTPS connections are opened for one URL. For the first time
- * the connection is opened through one proxy,
- * for the second time through another.
+ * Two HTTPS connections are opened for one URL: the first time the connection is opened
+ * through one proxy, the second time it is opened through another.
*/
public void testConsequentProxyConnection() throws Throwable {
- // setting up the properties pointing to the key/trust stores
+ // set up the properties pointing to the key/trust stores
setUpStoreProperties();
- // create the SSLServerSocket which will be used by server side
- ServerSocket ss = new ServerSocket(0);
+ // set the HostnameVerifier required to satisfy SSL - always returns "verified".
+ HttpsURLConnection.setDefaultHostnameVerifier(new TestHostnameVerifier());
- // create the HostnameVerifier to check that Hostname verification
- // is done
- TestHostnameVerifier hnv = new TestHostnameVerifier();
- HttpsURLConnection.setDefaultHostnameVerifier(hnv);
+ // create a server that pretends to be both a proxy and then the webserver
+ SingleRequestDispatcher getDispatcher1 = new SingleRequestDispatcher(GET_METHOD, OK_CODE);
+ MockWebServer proxyAndWebServer1 = createProxiedServer(getDispatcher1);
// create HttpsURLConnection to be tested
+ URL proxyUrl1 = proxyAndWebServer1.getUrl("/");
URL url = new URL("https://requested.host:55555/requested.data");
+ InetSocketAddress proxyAddress = new InetSocketAddress("localhost", proxyUrl1.getPort());
HttpsURLConnection connection = (HttpsURLConnection)
- url.openConnection(new Proxy(Proxy.Type.HTTP,
- new InetSocketAddress("localhost",
- ss.getLocalPort())));
+ url.openConnection(new Proxy(Proxy.Type.HTTP, proxyAddress));
connection.setSSLSocketFactory(getContext().getSocketFactory());
+ executeClientRequest(connection, false /* doOutput */);
+ checkConnectionStateParameters(connection, getDispatcher1.getLastRequest());
- // perform the interaction between the peers and check the results
- SSLSocket peerSocket = (SSLSocket) doInteraction(connection, ss);
- checkConnectionStateParameters(connection, peerSocket);
+ proxyAndWebServer1.shutdown();
- // create another SSLServerSocket which will be used by server side
- ss = new ServerSocket(0);
+ // create another server
+ SingleRequestDispatcher getDispatcher2 = new SingleRequestDispatcher(GET_METHOD, OK_CODE);
+ MockWebServer proxyAndWebServer2 = createProxiedServer(getDispatcher2);
- connection = (HttpsURLConnection) url.openConnection(new Proxy(
- Proxy.Type.HTTP, new InetSocketAddress("localhost", ss.getLocalPort())));
- connection.setSSLSocketFactory(getContext().getSocketFactory());
+ // create another HttpsURLConnection to be tested
+ URL proxyUrl2 = proxyAndWebServer2.getUrl("/");
+ InetSocketAddress proxyAddress2 = new InetSocketAddress("localhost", proxyUrl2.getPort());
+ HttpsURLConnection connection2 = (HttpsURLConnection) url.openConnection(
+ new Proxy(Proxy.Type.HTTP, proxyAddress2));
+ connection2.setSSLSocketFactory(getContext().getSocketFactory());
// perform the interaction between the peers and check the results
- peerSocket = (SSLSocket) doInteraction(connection, ss);
- checkConnectionStateParameters(connection, peerSocket);
+ executeClientRequest(connection2, false /* doOutput */);
+ checkConnectionStateParameters(connection2, getDispatcher2.getLastRequest());
+
+ proxyAndWebServer2.shutdown();
+ }
+
+ private static MockWebServer createProxiedServer(Dispatcher getDispatcher)
+ throws Exception {
+ // request 1: proxy CONNECT, respond with OK
+ ProxyConnectDispatcher proxyConnectDispatcher =
+ new ProxyConnectDispatcher(false /* authenticationRequired */);
+ // request 2: The get dispatcher.
+ DelegatingDispatcher delegatingDispatcher1 =
+ new DelegatingDispatcher(proxyConnectDispatcher, getDispatcher);
+ return createProxyAndWebServer(getContext(), delegatingDispatcher1);
}
/**
@@ -485,37 +532,47 @@ public class HttpsURLConnectionTest extends TestCase {
* Client sends data to the server.
*/
public void testProxyAuthConnection_doOutput() throws Throwable {
- // setting up the properties pointing to the key/trust stores
+ // set up the properties pointing to the key/trust stores
setUpStoreProperties();
- // create the SSLServerSocket which will be used by server side
- ServerSocket ss = new ServerSocket(0);
+ SSLContext ctx = getContext();
- // create the HostnameVerifier to check that Hostname verification
- // is done
- TestHostnameVerifier hnv = new TestHostnameVerifier();
- HttpsURLConnection.setDefaultHostnameVerifier(hnv);
+ // set the HostnameVerifier required to satisfy SSL - always returns "verified".
+ HttpsURLConnection.setDefaultHostnameVerifier(new TestHostnameVerifier());
Authenticator.setDefault(new Authenticator() {
-
protected PasswordAuthentication getPasswordAuthentication() {
- return new PasswordAuthentication("user", "password"
- .toCharArray());
+ return new PasswordAuthentication("user", "password".toCharArray());
}
});
+ // create a server that pretends to be both a proxy and then the webserver
+ // request 1: proxy CONNECT, respond with auth challenge
+ ProxyConnectAuthFailDispatcher authFailDispatcher = new ProxyConnectAuthFailDispatcher();
+ // request 2: proxy CONNECT, respond with OK
+ ProxyConnectDispatcher proxyConnectDispatcher =
+ new ProxyConnectDispatcher(true /* authenticationRequired */);
+ // request 3: tunnelled POST, respond with OK
+ SingleRequestDispatcher postDispatcher = new SingleRequestDispatcher(POST_METHOD, OK_CODE);
+ DelegatingDispatcher delegatingDispatcher = new DelegatingDispatcher(
+ authFailDispatcher, proxyConnectDispatcher, postDispatcher);
+ MockWebServer proxyAndWebServer = createProxyAndWebServer(ctx, delegatingDispatcher);
+ URL proxyUrl = proxyAndWebServer.getUrl("/");
+
// create HttpsURLConnection to be tested
- URL url = new URL("https://requested.host:55554/requested.data");
+ InetSocketAddress proxyAddress = new InetSocketAddress("localhost", proxyUrl.getPort());
HttpsURLConnection connection = (HttpsURLConnection)
- url.openConnection(new Proxy(Proxy.Type.HTTP,
- new InetSocketAddress("localhost",
- ss.getLocalPort())));
+ proxyUrl.openConnection(new Proxy(Proxy.Type.HTTP, proxyAddress));
connection.setSSLSocketFactory(getContext().getSocketFactory());
- connection.setDoOutput(true);
// perform the interaction between the peers and check the results
- SSLSocket peerSocket = (SSLSocket) doInteraction(connection, ss, OK_CODE, true);
- checkConnectionStateParameters(connection, peerSocket);
+ executeClientRequest(connection, true /* doOutput */);
+ checkConnectionStateParameters(connection, postDispatcher.getLastRequest());
+
+ // should silently exit
+ connection.connect();
+
+ proxyAndWebServer.shutdown();
}
/**
@@ -524,79 +581,82 @@ public class HttpsURLConnectionTest extends TestCase {
* (Authenticator was not set up in the system).
*/
public void testProxyAuthConnectionFailed() throws Throwable {
- // setting up the properties pointing to the key/trust stores
+ // set up the properties pointing to the key/trust stores
setUpStoreProperties();
- // create the SSLServerSocket which will be used by server side
- ServerSocket ss = new ServerSocket(0);
+ // set the HostnameVerifier required to satisfy SSL - always returns "verified".
+ HttpsURLConnection.setDefaultHostnameVerifier(new TestHostnameVerifier());
- // create the HostnameVerifier to check that Hostname verification
- // is done
- TestHostnameVerifier hnv = new TestHostnameVerifier();
- HttpsURLConnection.setDefaultHostnameVerifier(hnv);
+ // create a server that pretends to be both a proxy that requests authentication.
+ MockWebServer proxyAndWebServer = new MockWebServer();
+ ProxyConnectAuthFailDispatcher authFailDispatcher = new ProxyConnectAuthFailDispatcher();
+ proxyAndWebServer.setDispatcher(authFailDispatcher);
+ proxyAndWebServer.play();
// create HttpsURLConnection to be tested
+ URL proxyUrl = proxyAndWebServer.getUrl("/");
+ InetSocketAddress proxyAddress = new InetSocketAddress("localhost", proxyUrl.getPort());
URL url = new URL("https://requested.host:55555/requested.data");
HttpsURLConnection connection = (HttpsURLConnection)
- url.openConnection(new Proxy(Proxy.Type.HTTP,
- new InetSocketAddress("localhost",
- ss.getLocalPort())));
+ url.openConnection(new Proxy(Proxy.Type.HTTP, proxyAddress));
connection.setSSLSocketFactory(getContext().getSocketFactory());
// perform the interaction between the peers and check the results
try {
- doInteraction(connection, ss, AUTHENTICATION_REQUIRED_CODE, true);
+ executeClientRequest(connection, false);
} catch (IOException e) {
// SSL Tunnelling failed
if (DO_LOG) {
- System.out.println("Got expected IOException: "
- + e.getMessage());
+ System.out.println("Got expected IOException: " + e.getMessage());
}
}
}
/**
- * Tests the behaviour of HTTPS connection in case of unavailability
- * of requested resource.
+ * Tests the behaviour of HTTPS connection in case of unavailability of requested resource (as
+ * reported by the target web server).
*/
public void testProxyConnection_Not_Found_Response() throws Throwable {
- // setting up the properties pointing to the key/trust stores
+ // set up the properties pointing to the key/trust stores
setUpStoreProperties();
- // create the SSLServerSocket which will be used by server side
- ServerSocket ss = new ServerSocket(0);
+ SSLContext ctx = getContext();
- // create the HostnameVerifier to check that Hostname verification
- // is done
- TestHostnameVerifier hnv = new TestHostnameVerifier();
- HttpsURLConnection.setDefaultHostnameVerifier(hnv);
+ // set the HostnameVerifier required to satisfy SSL - always returns "verified".
+ HttpsURLConnection.setDefaultHostnameVerifier(new TestHostnameVerifier());
+
+ // create a server that pretends to be a proxy
+ ProxyConnectDispatcher proxyConnectDispatcher =
+ new ProxyConnectDispatcher(false /* authenticationRequired */);
+ SingleRequestDispatcher notFoundDispatcher =
+ new SingleRequestDispatcher(GET_METHOD, NOT_FOUND_CODE);
+ DelegatingDispatcher delegatingDispatcher =
+ new DelegatingDispatcher(proxyConnectDispatcher, notFoundDispatcher);
+ MockWebServer proxyAndWebServer = createProxyAndWebServer(ctx, delegatingDispatcher);
// create HttpsURLConnection to be tested
- URL url = new URL("https://localhost:" + ss.getLocalPort());
+ URL proxyUrl = proxyAndWebServer.getUrl("/");
+ InetSocketAddress proxyAddress = new InetSocketAddress("localhost", proxyUrl.getPort());
+ URL url = new URL("https://requested.host:55555/requested.data");
HttpsURLConnection connection = (HttpsURLConnection)
- url.openConnection(new Proxy(Proxy.Type.HTTP,
- new InetSocketAddress("localhost",
- ss.getLocalPort())));
+ url.openConnection(new Proxy(Proxy.Type.HTTP, proxyAddress));
connection.setSSLSocketFactory(getContext().getSocketFactory());
try {
- doInteraction(connection, ss, NOT_FOUND_CODE); // NOT FOUND
+ executeClientRequest(connection, false /* doOutput */);
fail("Expected exception was not thrown.");
} catch (FileNotFoundException e) {
if (DO_LOG) {
- System.out.println("Expected exception was thrown: "
- + e.getMessage());
+ System.out.println("Expected exception was thrown: " + e.getMessage());
}
}
}
- /**
- * Log the name of the test case to be executed.
- */
public void setUp() throws Exception {
super.setUp();
if (DO_LOG) {
+ // Log the name of the test case to be executed.
System.out.println();
System.out.println("------------------------");
System.out.println("------ " + getName());
@@ -604,8 +664,8 @@ public class HttpsURLConnectionTest extends TestCase {
}
if (store != null) {
- String ksFileName = ("org/apache/harmony/luni/tests/key_store."
- + KeyStore.getDefaultType().toLowerCase());
+ String ksFileName = "org/apache/harmony/luni/tests/key_store." +
+ KeyStore.getDefaultType().toLowerCase();
InputStream in = getClass().getClassLoader().getResourceAsStream(ksFileName);
FileOutputStream out = new FileOutputStream(store);
BufferedInputStream bufIn = new BufferedInputStream(in, 8192);
@@ -627,28 +687,21 @@ public class HttpsURLConnectionTest extends TestCase {
}
}
- /**
- * Checks the HttpsURLConnection getter's values and compares
- * them with actual corresponding values of remote peer.
- */
- public static void checkConnectionStateParameters(
- HttpsURLConnection clientConnection, SSLSocket serverPeer)
- throws Exception {
- SSLSession session = serverPeer.getSession();
-
- assertEquals(session.getCipherSuite(), clientConnection.getCipherSuite());
- assertEquals(session.getLocalPrincipal(), clientConnection.getPeerPrincipal());
- assertEquals(session.getPeerPrincipal(), clientConnection.getLocalPrincipal());
+ private static void checkConnectionStateParameters(
+ HttpsURLConnection connection, RecordedRequest request) throws Exception {
+ assertEquals(request.getSslCipherSuite(), connection.getCipherSuite());
+ assertEquals(request.getSslLocalPrincipal(), connection.getPeerPrincipal());
+ assertEquals(request.getSslPeerPrincipal(), connection.getLocalPrincipal());
- Certificate[] serverCertificates = clientConnection.getServerCertificates();
- Certificate[] localCertificates = session.getLocalCertificates();
+ Certificate[] serverCertificates = connection.getServerCertificates();
+ Certificate[] localCertificates = request.getSslLocalCertificates();
assertTrue("Server certificates differ from expected",
- Arrays.equals(serverCertificates, localCertificates));
+ Arrays.equals(serverCertificates, localCertificates));
- localCertificates = clientConnection.getLocalCertificates();
- serverCertificates = session.getPeerCertificates();
+ localCertificates = connection.getLocalCertificates();
+ serverCertificates = request.getSslPeerCertificates();
assertTrue("Local certificates differ from expected",
- Arrays.equals(serverCertificates, localCertificates));
+ Arrays.equals(serverCertificates, localCertificates));
}
/**
@@ -714,395 +767,233 @@ public class HttpsURLConnectionTest extends TestCase {
}
/**
- * Performs interaction between client's HttpsURLConnection and
- * servers side (ServerSocket).
+ * The host name verifier used in test.
*/
- public static Socket doInteraction(final HttpsURLConnection clientConnection,
- final ServerSocket serverSocket)
- throws Throwable {
- return doInteraction(clientConnection, serverSocket, OK_CODE, false);
+ static class TestHostnameVerifier implements HostnameVerifier {
+
+ boolean verified = false;
+
+ public boolean verify(String hostname, SSLSession session) {
+ if (DO_LOG) {
+ System.out.println("***> verification " + hostname + " "
+ + session.getPeerHost());
+ }
+ verified = true;
+ return true;
+ }
}
/**
- * Performs interaction between client's HttpsURLConnection and
- * servers side (ServerSocket). Server will response with specified
- * response code.
+ * Creates a {@link MockWebServer} that acts as both a proxy and then a web server with the
+ * supplied {@link SSLContext} and {@link Dispatcher}. The dispatcher provided must handle the
+ * CONNECT request/responses and {@link SocketPolicy} needed to simulate the hand-off from proxy
+ * to web server. See {@link HttpsURLConnectionTest.ProxyConnectDispatcher}.
*/
- public static Socket doInteraction(final HttpsURLConnection clientConnection,
- final ServerSocket serverSocket,
- final int responseCode)
- throws Throwable {
- return doInteraction(clientConnection, serverSocket, responseCode, false);
+ private static MockWebServer createProxyAndWebServer(SSLContext ctx, Dispatcher dispatcher)
+ throws IOException {
+ return createServer(ctx, dispatcher, true /* handleProxying */);
}
/**
- * Performs interaction between client's HttpsURLConnection and
- * servers side (ServerSocket). Server will response with specified
- * response code.
- * @param doAuthentication specifies
- * if the server needs client authentication.
+ * Creates a {@link MockWebServer} that acts as (only) a web server with the supplied
+ * {@link SSLContext} and {@link Dispatcher}.
*/
- public static Socket doInteraction(final HttpsURLConnection clientConnection,
- final ServerSocket serverSocket,
- final int responseCode,
- final boolean doAuthentication)
- throws Throwable {
- // set up the connection
- clientConnection.setDoInput(true);
- clientConnection.setConnectTimeout(TIMEOUT);
- clientConnection.setReadTimeout(TIMEOUT);
+ private static MockWebServer createWebServer(SSLContext ctx, Dispatcher dispatcher)
+ throws IOException {
+ return createServer(ctx, dispatcher, false /* handleProxying */);
+ }
- ServerWork server = new ServerWork(serverSocket, responseCode, doAuthentication);
+ private static MockWebServer createServer(
+ SSLContext ctx, Dispatcher dispatcher, boolean handleProxying)
+ throws IOException {
+ MockWebServer webServer = new MockWebServer();
+ webServer.useHttps(ctx.getSocketFactory(), handleProxying /* tunnelProxy */);
+ webServer.setDispatcher(dispatcher);
+ webServer.play();
+ return webServer;
+ }
- ClientConnectionWork client = new ClientConnectionWork(clientConnection);
+ /**
+ * A {@link Dispatcher} that has a list of dispatchers to delegate to, each of which will be
+ * used for one request and then discarded.
+ */
+ private static class DelegatingDispatcher extends Dispatcher {
+ private LinkedList<Dispatcher> delegates = new LinkedList<Dispatcher>();
- ExecutorService executorService = Executors.newFixedThreadPool(2);
- try {
- Future<Void> serverFuture = executorService.submit(server);
- Future<Void> clientFuture = executorService.submit(client);
-
- Throwable t = null;
- try {
- serverFuture.get(30, TimeUnit.SECONDS);
- } catch (ExecutionException e) {
- t = e.getCause();
- }
- try {
- clientFuture.get(30, TimeUnit.SECONDS);
- } catch (ExecutionException e) {
- // two problems? log the first before overwriting
- if (t != null) {
- t.printStackTrace();
- }
- t = e.getCause();
- }
- if (t != null) {
- throw t;
- }
- } catch (ExecutionException e) {
- throw e.getCause();
- } finally {
- executorService.shutdown();
+ public DelegatingDispatcher(Dispatcher... dispatchers) {
+ addAll(dispatchers);
+ }
+
+ private void addAll(Dispatcher... dispatchers) {
+ Collections.addAll(delegates, dispatchers);
+ }
+
+ @Override
+ public MockResponse dispatch(RecordedRequest request) throws InterruptedException {
+ return delegates.removeFirst().dispatch(request);
}
- return server.peerSocket;
+ @Override
+ public SocketPolicy peekSocketPolicy() {
+ return delegates.getFirst().peekSocketPolicy();
+ }
}
- /**
- * The host name verifier used in test.
- */
- static class TestHostnameVerifier implements HostnameVerifier {
+ /** Handles a request for SSL tunnel: Answers with a request to authenticate. */
+ private static class ProxyConnectAuthFailDispatcher extends Dispatcher {
- boolean verified = false;
+ @Override
+ public MockResponse dispatch(RecordedRequest request) throws InterruptedException {
+ assertEquals("CONNECT", request.getMethod());
- public boolean verify(String hostname, SSLSession session) {
- if (DO_LOG) {
- System.out.println("***> verification " + hostname + " "
- + session.getPeerHost());
- }
- verified = true;
- return true;
+ MockResponse response = new MockResponse();
+ response.setResponseCode(AUTHENTICATION_REQUIRED_CODE);
+ response.addHeader("Proxy-authenticate: Basic realm=\"localhost\"");
+ log("Authentication required. Sending response: " + response);
+ return response;
+ }
+
+ private void log(String msg) {
+ HttpsURLConnectionTest.log("ProxyConnectAuthFailDispatcher", msg);
}
}
/**
- * The base class for mock Client and Server.
+ * Handles a request for SSL tunnel: Answers with a success and the socket is upgraded to SSL.
*/
- static class Work {
-
- /**
- * The header of OK HTTP response.
- */
- static final String responseHead = "HTTP/1.1 200 OK\r\n";
-
- /**
- * The response message to be sent to the proxy CONNECT request.
- */
- static final String proxyResponse = responseHead + "\r\n";
-
- /**
- * The content of the response to be sent during HTTPS session.
- */
- static final String httpsResponseContent
- = "<HTML>\n"
- + "<HEAD><TITLE>HTTPS Response Content</TITLE></HEAD>\n"
- + "</HTML>";
-
- /**
- * The tail of the response to be sent during HTTPS session.
- */
- static final String httpsResponseTail
- = "Content-type: text/html\r\n"
- + "Content-length: " + httpsResponseContent.length() + "\r\n"
- + "\r\n"
- + httpsResponseContent;
-
- /**
- * The response requiring client's proxy authentication.
- */
- static final String respAuthenticationRequired
- = "HTTP/1.0 407 Proxy authentication required\r\n"
- + "Proxy-authenticate: Basic realm=\"localhost\"\r\n"
- + "\r\n";
-
- /**
- * The data to be posted by client to the server.
- */
- static final String clientsData = "_.-^ Client's Data ^-._";
-
- /**
- * The print stream used for debug log.
- * If it is null debug info will not be printed.
- */
- private PrintStream out = System.out;
-
- /**
- * Prints log message.
- */
- public synchronized void log(String message) {
- if (DO_LOG && (out != null)) {
- out.println("[" + this + "]: " + message);
+ private static class ProxyConnectDispatcher extends Dispatcher {
+
+ private final boolean authenticationRequired;
+
+ private ProxyConnectDispatcher(boolean authenticationRequired) {
+ this.authenticationRequired = authenticationRequired;
+ }
+
+ @Override
+ public MockResponse dispatch(RecordedRequest request) throws InterruptedException {
+ if (authenticationRequired) {
+ // check provided authorization credentials
+ assertNotNull("no proxy-authorization credentials: " + request,
+ request.getHeader("proxy-authorization"));
+ log("Got authenticated request:\n" + request);
+ log("------------------");
}
+
+ assertEquals("CONNECT", request.getMethod());
+ log("Send proxy response");
+ MockResponse response = new MockResponse();
+ response.setResponseCode(200);
+ response.setSocketPolicy(SocketPolicy.UPGRADE_TO_SSL_AT_END);
+ return response;
+ }
+
+ @Override
+ public SocketPolicy peekSocketPolicy() {
+ return SocketPolicy.UPGRADE_TO_SSL_AT_END;
+ }
+
+ private void log(String msg) {
+ HttpsURLConnectionTest.log("ProxyConnectDispatcher", msg);
}
}
/**
- * The class used for server side works.
+ * Handles a request: Answers with a response with a specified status code.
+ * If the {@code expectedMethod} is {@code POST} a hardcoded response body {@link #POST_DATA}
+ * will be included in the response.
*/
- static class ServerWork extends Work implements Callable<Void> {
-
- // the server socket used for connection
- private final ServerSocket serverSocket;
+ private static class SingleRequestDispatcher extends Dispatcher {
- // indicates if the server acts as proxy server
- private final boolean actAsProxy;
-
- // indicates if the server needs proxy authentication
- private final boolean needProxyAuthentication;
-
- // response code to be send to the client peer
+ private final String expectedMethod;
private final int responseCode;
- // the socket connected with client peer
- private Socket peerSocket;
-
- /**
- * Creates the thread acting as a server side.
- * @param serverSocket the server socket to be used during connection
- * @param responseCode the response code to be sent to the client
- * @param needProxyAuthentication
- * indicates if the server needs proxy authentication
- */
- public ServerWork(ServerSocket serverSocket,
- int responseCode,
- boolean needProxyAuthentication) {
- this.serverSocket = serverSocket;
+ private RecordedRequest lastRequest;
+
+ private SingleRequestDispatcher(String expectedMethod, int responseCode) {
this.responseCode = responseCode;
- this.needProxyAuthentication = needProxyAuthentication;
- // will act as a proxy server if the specified server socket
- // is not a secure server socket
- this.actAsProxy = !(serverSocket instanceof SSLServerSocket);
- if (!actAsProxy) {
- // demand client to send its certificate
- ((SSLServerSocket) serverSocket).setNeedClientAuth(true);
- }
+ this.expectedMethod = expectedMethod;
}
- /**
- * Closes the connection.
- */
- public void closeSocket(Socket socket) {
- if (socket == null) {
- return;
+ @Override
+ public MockResponse dispatch(RecordedRequest request) throws InterruptedException {
+ if (lastRequest != null) {
+ fail("More than one request received");
}
- try {
- socket.getInputStream().close();
- } catch (IOException e) {}
- try {
- socket.getOutputStream().close();
- } catch (IOException e) {}
- try {
- socket.close();
- } catch (IOException e) {}
+ log("Request received: " + request);
+ lastRequest = request;
+ assertEquals(expectedMethod, request.getMethod());
+ if (POST_METHOD.equals(expectedMethod)) {
+ assertEquals(POST_DATA, request.getUtf8Body());
+ }
+
+ MockResponse response = new MockResponse();
+ response.setResponseCode(responseCode);
+ response.setBody(RESPONSE_CONTENT);
+
+ log("Responding with: " + response);
+ return response;
}
- /**
- * Performs the actual server work.
- * If some exception occurs during the work it will be
- * stored in the <code>thrown</code> field.
- */
- public Void call() throws Exception {
- // the buffer used for reading the messages
- byte[] buff = new byte[2048];
- // the number of bytes read into the buffer
- try {
- // configure the server socket to avoid blocking
- serverSocket.setSoTimeout(TIMEOUT);
- // accept client connection
- peerSocket = serverSocket.accept();
- // configure the client connection to avoid blocking
- peerSocket.setSoTimeout(TIMEOUT);
- log("Client connection ACCEPTED");
-
- InputStream is = peerSocket.getInputStream();
- OutputStream os = peerSocket.getOutputStream();
-
- int num = is.read(buff);
- if (num == -1) {
- log("Unexpected EOF");
- return null;
- }
-
- String message = new String(buff, 0, num);
- log("Got request:\n" + message);
- log("------------------");
+ public RecordedRequest getLastRequest() {
+ return lastRequest;
+ }
- if (!actAsProxy) {
- // Act as Server (not Proxy) side
- if (message.startsWith("POST")) {
- // client connection sent some data
- log("try to read client data");
- String data = message.substring(message.indexOf("\r\n\r\n")+4);
- log("client's data: '" + data + "'");
- // check the received data
- assertEquals(clientsData, data);
- }
- } else {
- if (needProxyAuthentication) {
- // Do proxy work
- log("Authentication required...");
- // send Authentication Request
- os.write(respAuthenticationRequired.getBytes());
- // read request
- num = is.read(buff);
- if (num == -1) {
- // this connection was closed,
- // do clean up and create new one:
- closeSocket(peerSocket);
- peerSocket = serverSocket.accept();
- peerSocket.setSoTimeout(TIMEOUT);
- log("New client connection ACCEPTED");
- is = peerSocket.getInputStream();
- os = peerSocket.getOutputStream();
- num = is.read(buff);
- }
- message = new String(buff, 0, num);
- log("Got authenticated request:\n" + message);
- log("------------------");
- // check provided authorization credentials
- assertTrue("no proxy-authorization credentials: " + message,
- message.toLowerCase().indexOf("proxy-authorization:") != -1);
- }
-
- assertTrue(message.startsWith("CONNECT"));
- // request for SSL tunnel
- log("Send proxy response");
- os.write(proxyResponse.getBytes());
-
- log("Perform SSL Handshake...");
- // create sslSocket acting as a remote server peer
- SSLSocket sslSocket = (SSLSocket)
- getContext().getSocketFactory().createSocket(peerSocket,
- "localhost",
- peerSocket.getPort(),
- true); // do autoclose
- sslSocket.setUseClientMode(false);
- // demand client authentication
- sslSocket.setNeedClientAuth(true);
- sslSocket.startHandshake();
- peerSocket = sslSocket;
- is = peerSocket.getInputStream();
- os = peerSocket.getOutputStream();
-
- // read the HTTP request sent by secure connection
- // (HTTPS request)
- num = is.read(buff);
- message = new String(buff, 0, num);
- log("[Remote Server] Request from SSL tunnel:\n" + message);
- log("------------------");
-
- if (message.startsWith("POST")) {
- // client connection sent some data
- log("[Remote Server] try to read client data");
- String data = message.substring(message.indexOf("\r\n\r\n")+4);
- log("[Remote Server] client's data: '" + message + "'");
- // check the received data
- assertEquals(clientsData, data);
- }
-
- log("[Remote Server] Sending the response by SSL tunnel...");
- }
-
- // send the response with specified response code
- os.write(("HTTP/1.1 " + responseCode
- + " Message\r\n" + httpsResponseTail).getBytes());
- os.flush();
- os.close();
- log("Work is DONE actAsProxy=" + actAsProxy);
- return null;
- } finally {
- closeSocket(peerSocket);
- try {
- serverSocket.close();
- } catch (IOException e) {}
- }
+ @Override
+ public SocketPolicy peekSocketPolicy() {
+ return SocketPolicy.DISCONNECT_AT_END;
}
- @Override public String toString() {
- return actAsProxy ? "Proxy Server" : "Server";
+ private void log(String msg) {
+ HttpsURLConnectionTest.log("SingleRequestDispatcher", msg);
}
}
/**
- * The class used for client side work.
+ * Executes an HTTP request using the supplied connection. If {@code doOutput} is {@code true}
+ * the request made is a POST and the request body sent is {@link #POST_DATA}.
+ * If {@code doOutput} is {@code false} the request made is a GET. The response must be a
+ * success with a body {@link #RESPONSE_CONTENT}.
*/
- static class ClientConnectionWork extends Work implements Callable<Void> {
-
- // connection to be used to contact the server side
- private HttpsURLConnection connection;
-
- /**
- * Creates the thread acting as a client side.
- * @param connection connection to be used to contact the server side
- */
- public ClientConnectionWork(HttpsURLConnection connection) {
- this.connection = connection;
- log("Created over connection: " + connection.getClass());
- }
+ private static void executeClientRequest(
+ HttpsURLConnection connection, boolean doOutput) throws IOException {
- /**
- * Performs the actual client work.
- * If some exception occurs during the work it will be
- * stored in the <code>thrown<code> field.
- */
- public Void call() throws Exception {
- log("Opening the connection to " + connection.getURL());
- connection.connect();
- log("Connection has been ESTABLISHED, using proxy: " + connection.usingProxy());
- if (connection.getDoOutput()) {
- log("Posting data");
- // connection configured to post data, do so
- connection.getOutputStream().write(clientsData.getBytes());
- }
- // read the content of HTTP(s) response
- InputStream is = connection.getInputStream();
- log("Input Stream obtained");
- byte[] buff = new byte[2048];
- int num = 0;
- int byt = 0;
- while ((num < buff.length) && ((byt = is.read()) != -1)) {
- buff[num++] = (byte) byt;
- }
- String message = new String(buff, 0, num);
- log("Got content:\n" + message);
- log("------------------");
- log("Response code: " + connection.getResponseCode());
- assertEquals(httpsResponseContent, message);
- return null;
+ // set up the connection
+ connection.setDoInput(true);
+ connection.setConnectTimeout(TIMEOUT);
+ connection.setReadTimeout(TIMEOUT);
+ connection.setDoOutput(doOutput);
+
+ log("Client", "Opening the connection to " + connection.getURL());
+ connection.connect();
+ log("Client", "Connection has been ESTABLISHED, using proxy: " + connection.usingProxy());
+ if (doOutput) {
+ log("Client", "Posting data");
+ // connection configured to post data, do so
+ OutputStream os = connection.getOutputStream();
+ os.write(POST_DATA.getBytes());
+ }
+ // read the content of HTTP(s) response
+ InputStream is = connection.getInputStream();
+ log("Client", "Input Stream obtained");
+ byte[] buff = new byte[2048];
+ int num = 0;
+ int byt;
+ while ((num < buff.length) && ((byt = is.read()) != -1)) {
+ buff[num++] = (byte) byt;
}
+ String message = new String(buff, 0, num);
+ log("Client", "Got content:\n" + message);
+ log("Client", "------------------");
+ log("Client", "Response code: " + connection.getResponseCode());
+ assertEquals(RESPONSE_CONTENT, message);
+ }
- @Override public String toString() {
- return "Client Connection";
+ /**
+ * Prints log message.
+ */
+ public static synchronized void log(String origin, String message) {
+ if (DO_LOG) {
+ System.out.println("[" + origin + "]: " + message);
}
}
}