diff --git a/jetty-proxy/src/test/java/org/eclipse/jetty/proxy/ProxyTunnellingTest.java b/jetty-proxy/src/test/java/org/eclipse/jetty/proxy/ProxyTunnellingTest.java index 5bb708392ed..9db2204ead2 100644 --- a/jetty-proxy/src/test/java/org/eclipse/jetty/proxy/ProxyTunnellingTest.java +++ b/jetty-proxy/src/test/java/org/eclipse/jetty/proxy/ProxyTunnellingTest.java @@ -21,19 +21,26 @@ package org.eclipse.jetty.proxy; import java.io.IOException; import java.net.ConnectException; import java.net.URLEncoder; +import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicReference; import javax.servlet.ServletException; import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.eclipse.jetty.client.HttpClient; +import org.eclipse.jetty.client.api.Connection; import org.eclipse.jetty.client.api.ContentResponse; +import org.eclipse.jetty.client.api.Destination; import org.eclipse.jetty.client.api.ProxyConfiguration; +import org.eclipse.jetty.client.util.FutureResponseListener; import org.eclipse.jetty.client.util.StringContentProvider; import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.HttpMethod; import org.eclipse.jetty.http.HttpScheme; +import org.eclipse.jetty.http.HttpStatus; import org.eclipse.jetty.http.MimeTypes; import org.eclipse.jetty.server.Handler; import org.eclipse.jetty.server.HttpConnection; @@ -43,6 +50,7 @@ import org.eclipse.jetty.server.ServerConnector; import org.eclipse.jetty.server.handler.AbstractHandler; import org.eclipse.jetty.toolchain.test.MavenTestingUtils; import org.eclipse.jetty.toolchain.test.TestTracker; +import org.eclipse.jetty.util.Promise; import org.eclipse.jetty.util.ssl.SslContextFactory; import org.hamcrest.Matchers; import org.junit.After; @@ -119,7 +127,7 @@ public class ProxyTunnellingTest } @Test - public void testOneMessageSSL() throws Exception + public void testOneExchangeViaSSL() throws Exception { startSSLServer(new ServerHandler()); startProxy(); @@ -137,6 +145,7 @@ public class ProxyTunnellingTest .path("/echo?body=" + URLEncoder.encode(body, "UTF-8")) .send(); + assertEquals(HttpStatus.OK_200, response.getStatus()); String content = response.getContentAsString(); assertEquals(body, content); } @@ -147,7 +156,7 @@ public class ProxyTunnellingTest } @Test - public void testTwoMessagesSSL() throws Exception + public void testTwoExchangesViaSSL() throws Exception { startSSLServer(new ServerHandler()); startProxy(); @@ -165,6 +174,7 @@ public class ProxyTunnellingTest .path("/echo?body=" + URLEncoder.encode(body, "UTF-8")) .send(); + assertEquals(HttpStatus.OK_200, response1.getStatus()); String content = response1.getContentAsString(); assertEquals(body, content); @@ -178,6 +188,7 @@ public class ProxyTunnellingTest .content(new StringContentProvider(content)) .send(); + assertEquals(HttpStatus.OK_200, response2.getStatus()); content = response2.getContentAsString(); assertEquals(body, content); } @@ -187,6 +198,74 @@ public class ProxyTunnellingTest } } + @Test + public void testTwoConcurrentExchangesViaSSL() throws Exception + { + startSSLServer(new ServerHandler()); + startProxy(); + + final HttpClient httpClient = new HttpClient(sslContextFactory); + httpClient.setProxyConfiguration(new ProxyConfiguration("localhost", proxyPort())); + httpClient.start(); + + try + { + final AtomicReference connection = new AtomicReference<>(); + final CountDownLatch connectionLatch = new CountDownLatch(1); + String body1 = "BODY"; + ContentResponse response1 = httpClient.newRequest("localhost", serverConnector.getLocalPort()) + .scheme(HttpScheme.HTTPS.asString()) + .method(HttpMethod.GET) + .path("/echo?body=" + URLEncoder.encode(body1, "UTF-8")) + .onRequestCommit(new org.eclipse.jetty.client.api.Request.CommitListener() + { + @Override + public void onCommit(org.eclipse.jetty.client.api.Request request) + { + Destination destination = httpClient.getDestination(HttpScheme.HTTPS.asString(), "localhost", serverConnector.getLocalPort()); + destination.newConnection(new Promise.Adapter() + { + @Override + public void succeeded(Connection result) + { + connection.set(result); + connectionLatch.countDown(); + } + }); + } + }) + .send(); + + assertEquals(HttpStatus.OK_200, response1.getStatus()); + String content = response1.getContentAsString(); + assertEquals(body1, content); + + Assert.assertTrue(connectionLatch.await(5, TimeUnit.SECONDS)); + + String body2 = "body=" + body1; + org.eclipse.jetty.client.api.Request request2 = httpClient.newRequest("localhost", serverConnector.getLocalPort()) + .scheme(HttpScheme.HTTPS.asString()) + .method(HttpMethod.POST) + .path("/echo") + .header(HttpHeader.CONTENT_TYPE, MimeTypes.Type.FORM_ENCODED.asString()) + .header(HttpHeader.CONTENT_LENGTH, String.valueOf(body2.length())) + .content(new StringContentProvider(body2)); + + // Make sure the second connection can send the exchange via the tunnel + FutureResponseListener listener2 = new FutureResponseListener(request2); + connection.get().send(request2, listener2); + ContentResponse response2 = listener2.get(5, TimeUnit.SECONDS); + + assertEquals(HttpStatus.OK_200, response2.getStatus()); + String content2 = response1.getContentAsString(); + assertEquals(body1, content2); + } + finally + { + httpClient.stop(); + } + } + @Test public void testProxyDown() throws Exception {