diff --git a/src/main/java/org/littleshoot/proxy/MitmManager.java b/src/main/java/org/littleshoot/proxy/MitmManager.java
index 7ba17eb35..996993766 100644
--- a/src/main/java/org/littleshoot/proxy/MitmManager.java
+++ b/src/main/java/org/littleshoot/proxy/MitmManager.java
@@ -1,7 +1,6 @@
package org.littleshoot.proxy;
import io.netty.handler.codec.http.HttpRequest;
-
import javax.net.ssl.SSLEngine;
import javax.net.ssl.SSLSession;
@@ -16,7 +15,7 @@ public interface MitmManager {
*
* @param peerHost to start a client connection to the server.
* @param peerPort to start a client connection to the server.
- *
+ *
* @return an SSLEngine used to connect to an upstream server
*/
SSLEngine serverSslEngine(String peerHost, int peerPort);
@@ -33,13 +32,13 @@ public interface MitmManager {
* Creates an {@link SSLEngine} for encrypting the client connection based
* on the given serverSslSession.
*
- *
+ *
*
* The serverSslSession is provided in case this method needs to inspect the
* server's certificates or something else about the encryption on the way
* to the server.
*
- *
+ *
*
* This is the place where one would implement impersonation of the server
* by issuing replacement certificates signed by the proxy's own
diff --git a/src/main/java/org/littleshoot/proxy/SelectiveMitmManager.java b/src/main/java/org/littleshoot/proxy/SelectiveMitmManager.java
new file mode 100755
index 000000000..3b758a9ca
--- /dev/null
+++ b/src/main/java/org/littleshoot/proxy/SelectiveMitmManager.java
@@ -0,0 +1,18 @@
+package org.littleshoot.proxy;
+
+/**
+ * An extension to the {@link MitmManager} interface to allow MITM to be
+ * selectively applied based on the peer. Added as a new interface to not
+ * break existing implementations.
+ */
+public interface SelectiveMitmManager extends MitmManager {
+ /**
+ * Checks if MITM should be applied for a given peer.
+ *
+ * @param peerHost The peer host
+ * @param peerPort The peer port
+ *
+ * @return true to continue with MITM, false to act as if MITM was not enabled for this peer and tunnel raw content.
+ */
+ boolean shouldMITMPeer(String peerHost, int peerPort);
+}
diff --git a/src/main/java/org/littleshoot/proxy/SelectiveMitmManagerAdapter.java b/src/main/java/org/littleshoot/proxy/SelectiveMitmManagerAdapter.java
new file mode 100755
index 000000000..288f9c210
--- /dev/null
+++ b/src/main/java/org/littleshoot/proxy/SelectiveMitmManagerAdapter.java
@@ -0,0 +1,31 @@
+package org.littleshoot.proxy;
+
+import io.netty.handler.codec.http.HttpRequest;
+import javax.net.ssl.SSLEngine;
+import javax.net.ssl.SSLSession;
+
+/**
+ * Convenience base class for adapting a non-selective-{@link MitmManager} into a {@link SelectiveMitmManager}.
+ */
+public abstract class SelectiveMitmManagerAdapter implements SelectiveMitmManager {
+ private final MitmManager childMitmManager;
+
+ public SelectiveMitmManagerAdapter(MitmManager childMitmManager) {
+ this.childMitmManager = childMitmManager;
+ }
+
+ @Override
+ public SSLEngine serverSslEngine(String peerHost, int peerPort) {
+ return this.childMitmManager.serverSslEngine(peerHost, peerPort);
+ }
+
+ @Override
+ public SSLEngine serverSslEngine() {
+ return this.childMitmManager.serverSslEngine();
+ }
+
+ @Override
+ public SSLEngine clientSslEngineFor(HttpRequest httpRequest, SSLSession serverSslSession) {
+ return this.childMitmManager.clientSslEngineFor(httpRequest, serverSslSession);
+ }
+}
diff --git a/src/main/java/org/littleshoot/proxy/impl/ProxyToServerConnection.java b/src/main/java/org/littleshoot/proxy/impl/ProxyToServerConnection.java
index b612f5160..4c84f8330 100644
--- a/src/main/java/org/littleshoot/proxy/impl/ProxyToServerConnection.java
+++ b/src/main/java/org/littleshoot/proxy/impl/ProxyToServerConnection.java
@@ -39,6 +39,7 @@
import org.littleshoot.proxy.FullFlowContext;
import org.littleshoot.proxy.HttpFilters;
import org.littleshoot.proxy.MitmManager;
+import org.littleshoot.proxy.SelectiveMitmManager;
import org.littleshoot.proxy.TransportProtocol;
import org.littleshoot.proxy.UnknownTransportProtocolException;
@@ -56,15 +57,14 @@
import static org.littleshoot.proxy.impl.ConnectionState.AWAITING_INITIAL;
import static org.littleshoot.proxy.impl.ConnectionState.CONNECTING;
import static org.littleshoot.proxy.impl.ConnectionState.DISCONNECTED;
-import static org.littleshoot.proxy.impl.ConnectionState.HANDSHAKING;
-
+import static org.littleshoot.proxy.impl.ConnectionState.HANDSHAKING;;
/**
*
* Represents a connection from our proxy to a server on the web.
* ProxyConnections are reused fairly liberally, and can go from disconnected to
* connected, back to disconnected and so on.
*
- *
+ *
*
* Connecting a {@link ProxyToServerConnection} can involve more than just
* connecting the underlying {@link Channel}. In particular, the connection may
@@ -134,13 +134,13 @@ public class ProxyToServerConnection extends ProxyConnection {
private volatile GlobalTrafficShapingHandler trafficHandler;
/**
- * Minimum size of the adaptive recv buffer when throttling is enabled.
+ * Minimum size of the adaptive recv buffer when throttling is enabled.
*/
private static final int MINIMUM_RECV_BUFFER_SIZE_BYTES = 64;
-
+
/**
* Create a new ProxyToServerConnection.
- *
+ *
* @param proxyServer
* @param clientConnection
* @param serverHostAndPort
@@ -262,12 +262,12 @@ protected void readRaw(ByteBuf buf) {
* doesn't know that any given response is to a HEAD request, so it needs to
* be told that there's no content so that it doesn't hang waiting for it.
*
- *
+ *
*
* See the documentation for {@link HttpResponseDecoder} for information
* about why HEAD requests need special handling.
*
- *
+ *
*
* Thanks to nataliakoval for
* pointing out that with connections being reused as they are, this needs
@@ -302,7 +302,7 @@ protected boolean isContentAlwaysEmpty(HttpMessage httpMessage) {
/**
* Like {@link #write(Object)} and also sets the current filters to the
* given value.
- *
+ *
* @param msg
* @param filters
*/
@@ -497,7 +497,7 @@ protected HttpFilters getHttpFiltersFromProxyServer(HttpRequest httpRequest) {
/**
* Keeps track of the current HttpResponse so that we can associate its
* headers with future related chunks for this same transfer.
- *
+ *
* @param response
*/
private void rememberCurrentResponse(HttpResponse response) {
@@ -512,7 +512,7 @@ private void rememberCurrentResponse(HttpResponse response) {
/**
* Respond to the client with the given {@link HttpObject}.
- *
+ *
* @param httpObject
*/
private void respondWith(HttpObject httpObject) {
@@ -554,31 +554,39 @@ private void initializeConnectionFlow() {
if (hasUpstreamChainedProxy()) {
connectionFlow.then(
serverConnection.HTTPCONNECTWithChainedProxy);
- }
-
+ }
+
MitmManager mitmManager = proxyServer.getMitmManager();
- boolean isMitmEnabled = mitmManager != null;
+ boolean shouldMITM = mitmManager != null;
- if (isMitmEnabled) {
+ if (shouldMITM) {
// When MITM is enabled and when chained proxy is set up, remoteAddress
// will be the chained proxy's address. So we use serverHostAndPort
// which is the end server's address.
HostAndPort parsedHostAndPort = HostAndPort.fromString(serverHostAndPort);
- // SNI may be disabled for this request due to a previous failed attempt to connect to the server
- // with SNI enabled.
- if (disableSni) {
- connectionFlow.then(serverConnection.EncryptChannel(proxyServer.getMitmManager()
- .serverSslEngine()));
- } else {
- connectionFlow.then(serverConnection.EncryptChannel(proxyServer.getMitmManager()
- .serverSslEngine(parsedHostAndPort.getHost(), parsedHostAndPort.getPort())));
+ // Potentially skip MITM
+ if (mitmManager instanceof SelectiveMitmManager) {
+ shouldMITM = ((SelectiveMitmManager)mitmManager).shouldMITMPeer(parsedHostAndPort.getHost(), parsedHostAndPort.getPort());
}
- connectionFlow
- .then(clientConnection.RespondCONNECTSuccessful)
- .then(serverConnection.MitmEncryptClientChannel);
- } else {
+ if (shouldMITM) {
+ // SNI may be disabled for this request due to a previous failed attempt to connect to the server
+ // with SNI enabled.
+ if (disableSni) {
+ connectionFlow.then(serverConnection.EncryptChannel(mitmManager
+ .serverSslEngine()));
+ } else {
+ connectionFlow.then(serverConnection.EncryptChannel(mitmManager
+ .serverSslEngine(parsedHostAndPort.getHost(), parsedHostAndPort.getPort())));
+ }
+
+ connectionFlow
+ .then(clientConnection.RespondCONNECTSuccessful)
+ .then(serverConnection.MitmEncryptClientChannel);
+ }
+ }
+ if (!shouldMITM) {
connectionFlow.then(serverConnection.StartTunneling)
.then(clientConnection.RespondCONNECTSuccessful)
.then(clientConnection.StartTunneling);
@@ -699,7 +707,7 @@ void read(ConnectionFlow flow, Object msg) {
*
* Encrypts the client channel based on our server {@link SSLSession}.
*
- *
+ *
*
* This does not wait for the handshake to finish so that we can go on and
* respond to the CONNECT request.
@@ -809,7 +817,7 @@ private void resetConnectionForRetry() throws UnknownHostException {
/**
* Set up our connection parameters based on server address and chained
* proxies.
- *
+ *
* @throws UnknownHostException when unable to resolve the hostname to an IP address
*/
private void setupConnectionParameters() throws UnknownHostException {
@@ -854,15 +862,15 @@ private void setupConnectionParameters() throws UnknownHostException {
/**
* Initialize our {@link ChannelPipeline} to connect the upstream server.
* LittleProxy acts as a client here.
- *
+ *
* A {@link ChannelPipeline} invokes the read (Inbound) handlers in
* ascending ordering of the list and then the write (Outbound) handlers in
* descending ordering.
- *
+ *
* Regarding the Javadoc of {@link HttpObjectAggregator} it's needed to have
* the {@link HttpResponseEncoder} or {@link HttpRequestEncoder} before the
* {@link HttpObjectAggregator} in the {@link ChannelPipeline}.
- *
+ *
* @param pipeline
* @param httpRequest
*/
@@ -906,7 +914,7 @@ private void initChannelPipeline(ChannelPipeline pipeline,
* Do all the stuff that needs to be done after our {@link ConnectionFlow}
* has succeeded.
*
- *
+ *
* @param shouldForwardInitialRequest
* whether or not we should forward the initial HttpRequest to
* the server after the connection has been established.
@@ -941,7 +949,7 @@ void connectionSucceeded(boolean shouldForwardInitialRequest) {
/**
* Build an {@link InetSocketAddress} for the given hostAndPort.
- *
+ *
* @param hostAndPort String representation of the host and port
* @param proxyServer the current {@link DefaultHttpProxyServer}
* @return a resolved InetSocketAddress for the specified hostAndPort
@@ -966,7 +974,7 @@ public static InetSocketAddress addressFor(String hostAndPort, DefaultHttpProxyS
/***************************************************************************
* Activity Tracking/Statistics
- *
+ *
* We track statistics on bytes, requests and responses by adding handlers
* at the appropriate parts of the pipeline (see initChannelPipeline()).
**************************************************************************/
diff --git a/src/test/java/org/littleshoot/proxy/BaseMitmProxyTest.java b/src/test/java/org/littleshoot/proxy/BaseMitmProxyTest.java
new file mode 100755
index 000000000..6394e50b6
--- /dev/null
+++ b/src/test/java/org/littleshoot/proxy/BaseMitmProxyTest.java
@@ -0,0 +1,146 @@
+package org.littleshoot.proxy;
+
+import io.netty.handler.codec.http.HttpContent;
+import io.netty.handler.codec.http.HttpMethod;
+import io.netty.handler.codec.http.HttpObject;
+import io.netty.handler.codec.http.HttpRequest;
+import io.netty.handler.codec.http.HttpResponse;
+import java.nio.charset.Charset;
+import java.util.HashSet;
+import java.util.Set;
+import org.littleshoot.proxy.extras.SelfSignedMitmManager;
+
+import static org.hamcrest.Matchers.hasItem;
+import static org.hamcrest.Matchers.not;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
+
+/**
+ * Base class for testing a single basic proxy running as a man in the middle.
+ */
+public abstract class BaseMitmProxyTest extends BaseProxyTest {
+ private Set requestPreMethodsSeen = new HashSet();
+ private Set requestPostMethodsSeen = new HashSet();
+ private StringBuilder responsePreBody = new StringBuilder();
+ private StringBuilder responsePostBody = new StringBuilder();
+ private Set responsePreOriginalRequestMethodsSeen = new HashSet();
+ private Set responsePostOriginalRequestMethodsSeen = new HashSet();
+
+ protected MitmManager getMitmManager() {
+ return new SelfSignedMitmManager();
+ }
+
+ @Override
+ protected void setUp() {
+ this.proxyServer = bootstrapProxy()
+ .withPort(0)
+ .withManInTheMiddle(this.getMitmManager())
+ .withFiltersSource(new HttpFiltersSourceAdapter() {
+ @Override
+ public HttpFilters filterRequest(HttpRequest originalRequest) {
+ return new HttpFiltersAdapter(originalRequest) {
+ @Override
+ public HttpResponse clientToProxyRequest(
+ HttpObject httpObject) {
+ if (httpObject instanceof HttpRequest) {
+ requestPreMethodsSeen
+ .add(((HttpRequest) httpObject)
+ .getMethod());
+ }
+ return null;
+ }
+
+ @Override
+ public HttpResponse proxyToServerRequest(
+ HttpObject httpObject) {
+ if (httpObject instanceof HttpRequest) {
+ requestPostMethodsSeen
+ .add(((HttpRequest) httpObject)
+ .getMethod());
+ }
+ return null;
+ }
+
+ @Override
+ public HttpObject serverToProxyResponse(
+ HttpObject httpObject) {
+ if (httpObject instanceof HttpResponse) {
+ responsePreOriginalRequestMethodsSeen
+ .add(originalRequest.getMethod());
+ } else if (httpObject instanceof HttpContent) {
+ responsePreBody.append(((HttpContent) httpObject)
+ .content().toString(
+ Charset.forName("UTF-8")));
+ }
+ return httpObject;
+ }
+
+ @Override
+ public HttpObject proxyToClientResponse(
+ HttpObject httpObject) {
+ if (httpObject instanceof HttpResponse) {
+ responsePostOriginalRequestMethodsSeen
+ .add(originalRequest.getMethod());
+ } else if (httpObject instanceof HttpContent) {
+ responsePostBody.append(((HttpContent) httpObject)
+ .content().toString(
+ Charset.forName("UTF-8")));
+ }
+ return httpObject;
+ }
+ };
+ }
+ })
+ .start();
+ }
+
+ protected void assertMethodSeenInRequestFilters(HttpMethod method) {
+ assertThat(method
+ + " should have been seen in clientToProxyRequest filter",
+ requestPreMethodsSeen, hasItem(method));
+ assertThat(method
+ + " should have been seen in proxyToServerRequest filter",
+ requestPostMethodsSeen, hasItem(method));
+ }
+
+ protected void assertMethodSeenInResponseFilters(HttpMethod method) {
+ assertThat(
+ method
+ + " should have been seen as the original requests's method in serverToProxyResponse filter",
+ responsePreOriginalRequestMethodsSeen, hasItem(method));
+ assertThat(
+ method
+ + " should have been seen as the original requests's method in proxyToClientResponse filter",
+ responsePostOriginalRequestMethodsSeen, hasItem(method));
+ }
+
+ protected void assertMethodNotSeenInRequestFilters(HttpMethod method) {
+ assertThat(method
+ + " should have not been seen in clientToProxyRequest filter",
+ requestPreMethodsSeen, not(hasItem(method)));
+ assertThat(method
+ + " should have not been seen in proxyToServerRequest filter",
+ requestPostMethodsSeen, not(hasItem(method)));
+ }
+
+ protected void assertMethodNotSeenInResponseFilters(HttpMethod method) {
+ assertThat(
+ method
+ + " should have not been seen as the original requests's method in serverToProxyResponse filter",
+ responsePreOriginalRequestMethodsSeen, not(hasItem(method)));
+ assertThat(
+ method
+ + " should have not been seen as the original requests's method in proxyToClientResponse filter",
+ responsePostOriginalRequestMethodsSeen, not(hasItem(method)));
+ }
+
+ protected void assertResponseFromFiltersMatchesActualResponse() {
+ assertEquals(
+ "Data received through HttpFilters.serverToProxyResponse should match response",
+ lastResponse, responsePreBody.toString());
+ assertEquals(
+ "Data received through HttpFilters.proxyToClientResponse should match response",
+ lastResponse, responsePostBody.toString());
+ }
+
+}
diff --git a/src/test/java/org/littleshoot/proxy/MitmProxyTest.java b/src/test/java/org/littleshoot/proxy/MitmProxyTest.java
index 7b2853a19..022d01503 100644
--- a/src/test/java/org/littleshoot/proxy/MitmProxyTest.java
+++ b/src/test/java/org/littleshoot/proxy/MitmProxyTest.java
@@ -1,96 +1,11 @@
package org.littleshoot.proxy;
-import io.netty.handler.codec.http.HttpContent;
import io.netty.handler.codec.http.HttpMethod;
-import io.netty.handler.codec.http.HttpObject;
-import io.netty.handler.codec.http.HttpRequest;
-import io.netty.handler.codec.http.HttpResponse;
-import org.littleshoot.proxy.extras.SelfSignedMitmManager;
-
-import java.nio.charset.Charset;
-import java.util.HashSet;
-import java.util.Queue;
-import java.util.Set;
-
-import static org.hamcrest.Matchers.hasItem;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertThat;
/**
* Tests just a single basic proxy running as a man in the middle.
*/
-public class MitmProxyTest extends BaseProxyTest {
- private Set requestPreMethodsSeen = new HashSet();
- private Set requestPostMethodsSeen = new HashSet();
- private StringBuilder responsePreBody = new StringBuilder();
- private StringBuilder responsePostBody = new StringBuilder();
- private Set responsePreOriginalRequestMethodsSeen = new HashSet();
- private Set responsePostOriginalRequestMethodsSeen = new HashSet();
-
- @Override
- protected void setUp() {
- this.proxyServer = bootstrapProxy()
- .withPort(0)
- .withManInTheMiddle(new SelfSignedMitmManager())
- .withFiltersSource(new HttpFiltersSourceAdapter() {
- @Override
- public HttpFilters filterRequest(HttpRequest originalRequest) {
- return new HttpFiltersAdapter(originalRequest) {
- @Override
- public HttpResponse clientToProxyRequest(
- HttpObject httpObject) {
- if (httpObject instanceof HttpRequest) {
- requestPreMethodsSeen
- .add(((HttpRequest) httpObject)
- .getMethod());
- }
- return null;
- }
-
- @Override
- public HttpResponse proxyToServerRequest(
- HttpObject httpObject) {
- if (httpObject instanceof HttpRequest) {
- requestPostMethodsSeen
- .add(((HttpRequest) httpObject)
- .getMethod());
- }
- return null;
- }
-
- @Override
- public HttpObject serverToProxyResponse(
- HttpObject httpObject) {
- if (httpObject instanceof HttpResponse) {
- responsePreOriginalRequestMethodsSeen
- .add(originalRequest.getMethod());
- } else if (httpObject instanceof HttpContent) {
- responsePreBody.append(((HttpContent) httpObject)
- .content().toString(
- Charset.forName("UTF-8")));
- }
- return httpObject;
- }
-
- @Override
- public HttpObject proxyToClientResponse(
- HttpObject httpObject) {
- if (httpObject instanceof HttpResponse) {
- responsePostOriginalRequestMethodsSeen
- .add(originalRequest.getMethod());
- } else if (httpObject instanceof HttpContent) {
- responsePostBody.append(((HttpContent) httpObject)
- .content().toString(
- Charset.forName("UTF-8")));
- }
- return httpObject;
- }
- };
- }
- })
- .start();
- }
-
+public class MitmProxyTest extends BaseMitmProxyTest {
@Override
protected boolean isMITM() {
return true;
@@ -129,34 +44,4 @@ public void testSimplePostRequestOverHTTPS() throws Exception {
assertMethodSeenInResponseFilters(HttpMethod.POST);
assertResponseFromFiltersMatchesActualResponse();
}
-
- private void assertMethodSeenInRequestFilters(HttpMethod method) {
- assertThat(method
- + " should have been seen in clientToProxyRequest filter",
- requestPreMethodsSeen, hasItem(method));
- assertThat(method
- + " should have been seen in proxyToServerRequest filter",
- requestPostMethodsSeen, hasItem(method));
- }
-
- private void assertMethodSeenInResponseFilters(HttpMethod method) {
- assertThat(
- method
- + " should have been seen as the original requests's method in serverToProxyResponse filter",
- responsePreOriginalRequestMethodsSeen, hasItem(method));
- assertThat(
- method
- + " should have been seen as the original requests's method in proxyToClientResponse filter",
- responsePostOriginalRequestMethodsSeen, hasItem(method));
- }
-
- private void assertResponseFromFiltersMatchesActualResponse() {
- assertEquals(
- "Data received through HttpFilters.serverToProxyResponse should match response",
- lastResponse, responsePreBody.toString());
- assertEquals(
- "Data received through HttpFilters.proxyToClientResponse should match response",
- lastResponse, responsePostBody.toString());
- }
-
}
diff --git a/src/test/java/org/littleshoot/proxy/SelectiveMitmProxyTest.java b/src/test/java/org/littleshoot/proxy/SelectiveMitmProxyTest.java
new file mode 100755
index 000000000..14f87a989
--- /dev/null
+++ b/src/test/java/org/littleshoot/proxy/SelectiveMitmProxyTest.java
@@ -0,0 +1,83 @@
+package org.littleshoot.proxy;
+
+import com.google.common.net.HostAndPort;
+import io.netty.handler.codec.http.HttpMethod;
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.http.HttpHost;
+
+import static org.hamcrest.Matchers.empty;
+import static org.hamcrest.Matchers.equalTo;
+import static org.hamcrest.Matchers.hasSize;
+import static org.hamcrest.Matchers.is;
+import static org.junit.Assert.assertThat;
+
+/**
+ * Tests just a single basic proxy running as a man in the middle, where the
+ * MTM manager is a selective manager, that for the purpose of the tests, always
+ * returns false.
+ */
+public class SelectiveMitmProxyTest extends BaseMitmProxyTest {
+ private List mitmRequests = new ArrayList<>();
+
+ @Override
+ protected boolean isMITM() {
+ return false;
+ }
+
+ @Override
+ protected MitmManager getMitmManager() {
+ return new SelectiveMitmManagerAdapter(super.getMitmManager()) {
+ @Override
+ public boolean shouldMITMPeer(String peerHost, int peerPort) {
+ mitmRequests.add(HostAndPort.fromParts(peerHost, peerPort));
+ return false;
+ }
+ };
+ }
+
+ @Override
+ public void testSimpleGetRequest() throws Exception {
+ super.testSimpleGetRequest();
+ assertMethodSeenInRequestFilters(HttpMethod.GET);
+ assertMethodSeenInResponseFilters(HttpMethod.GET);
+ assertNoMitmChecks();
+ assertResponseFromFiltersMatchesActualResponse();
+ }
+
+ @Override
+ public void testSimpleGetRequestOverHTTPS() throws Exception {
+ super.testSimpleGetRequestOverHTTPS();
+ assertMethodSeenInRequestFilters(HttpMethod.CONNECT);
+ assertSingleMitmCheck(httpsWebHost);
+ assertMethodNotSeenInRequestFilters(HttpMethod.GET);
+ assertMethodNotSeenInRequestFilters(HttpMethod.GET);
+ }
+
+ @Override
+ public void testSimplePostRequest() throws Exception {
+ super.testSimplePostRequest();
+ assertMethodSeenInRequestFilters(HttpMethod.POST);
+ assertMethodSeenInResponseFilters(HttpMethod.POST);
+ assertNoMitmChecks();
+ assertResponseFromFiltersMatchesActualResponse();
+ }
+
+ @Override
+ public void testSimplePostRequestOverHTTPS() throws Exception {
+ super.testSimplePostRequestOverHTTPS();
+ assertMethodSeenInRequestFilters(HttpMethod.CONNECT);
+ assertSingleMitmCheck(httpsWebHost);
+ assertMethodNotSeenInRequestFilters(HttpMethod.POST);
+ assertMethodNotSeenInRequestFilters(HttpMethod.POST);
+ }
+
+ private void assertNoMitmChecks() {
+ assertThat(mitmRequests, is(empty()));
+ }
+
+ private void assertSingleMitmCheck(HttpHost host) {
+ assertThat(mitmRequests, hasSize(1));
+ assertThat(mitmRequests.get(0), is(equalTo(HostAndPort.fromParts(host.getHostName(), host.getPort()))));
+ }
+}