From 3b18490eada15f896c67a287f1d9a495a0465b6d Mon Sep 17 00:00:00 2001 From: Simone Bordet Date: Thu, 25 Jul 2013 16:08:02 +0200 Subject: [PATCH 1/3] 409028 - Jetty HttpClient does not work with proxy CONNECT method. The problem was due to the fact that the server replied with HTTP/1.0 to the CONNECT request; because of this, the parser was set as non persistent, and the tunnel was immediately closed. Now we are setting the parser as persistent if the method is a CONNECT, no matter what HTTP version the server specifies. --- .../jetty/client/AbstractHttpConnection.java | 7 ++- .../jetty/client/ProxyTunnellingTest.java | 60 +++++++++++++++++-- 2 files changed, 60 insertions(+), 7 deletions(-) diff --git a/jetty-client/src/main/java/org/eclipse/jetty/client/AbstractHttpConnection.java b/jetty-client/src/main/java/org/eclipse/jetty/client/AbstractHttpConnection.java index 12560b3d1b2..916f082e0ff 100644 --- a/jetty-client/src/main/java/org/eclipse/jetty/client/AbstractHttpConnection.java +++ b/jetty-client/src/main/java/org/eclipse/jetty/client/AbstractHttpConnection.java @@ -36,7 +36,6 @@ import org.eclipse.jetty.http.HttpVersions; import org.eclipse.jetty.io.AbstractConnection; import org.eclipse.jetty.io.Buffer; import org.eclipse.jetty.io.Buffers; -import org.eclipse.jetty.io.ByteArrayBuffer; import org.eclipse.jetty.io.Connection; import org.eclipse.jetty.io.EndPoint; import org.eclipse.jetty.io.EofException; @@ -318,7 +317,11 @@ public abstract class AbstractHttpConnection extends AbstractConnection implemen { HttpExchange exchange = _exchange; if (exchange!=null) + { exchange.setStatus(HttpExchange.STATUS_PARSING_CONTENT); + if (HttpMethods.CONNECT.equalsIgnoreCase(exchange.getMethod())) + _parser.setPersistent(true); + } } @Override @@ -350,8 +353,6 @@ public abstract class AbstractHttpConnection extends AbstractConnection implemen } } } - - } @Override diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/ProxyTunnellingTest.java b/jetty-client/src/test/java/org/eclipse/jetty/client/ProxyTunnellingTest.java index 550c5418ea0..c887d1fb2fa 100644 --- a/jetty-client/src/test/java/org/eclipse/jetty/client/ProxyTunnellingTest.java +++ b/jetty-client/src/test/java/org/eclipse/jetty/client/ProxyTunnellingTest.java @@ -20,6 +20,7 @@ package org.eclipse.jetty.client; import java.io.IOException; import java.io.InterruptedIOException; +import java.net.Socket; import java.net.URLEncoder; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; @@ -46,6 +47,7 @@ import org.eclipse.jetty.toolchain.test.MavenTestingUtils; import org.eclipse.jetty.util.ssl.SslContextFactory; import org.junit.After; import org.junit.Assert; +import org.junit.Assume; import org.junit.Test; import static org.junit.Assert.assertEquals; @@ -106,14 +108,20 @@ public class ProxyTunnellingTest protected void stopServer() throws Exception { - server.stop(); - server.join(); + if (server != null) + { + server.stop(); + server.join(); + } } protected void stopProxy() throws Exception { - proxy.stop(); - proxy.join(); + if (proxy != null) + { + proxy.stop(); + proxy.join(); + } } @Test @@ -337,6 +345,50 @@ public class ProxyTunnellingTest } } + @Test + public void testExternalProxy() throws Exception + { + // Free proxy server obtained from http://hidemyass.com/proxy-list/ + String proxyHost = "81.208.25.53"; + int proxyPort = 3128; + try + { + new Socket(proxyHost, proxyPort).close(); + } + catch (IOException x) + { + Assume.assumeNoException(x); + } + + // Start the server to start the SslContextFactory + startSSLServer(new AbstractHandler() + { + public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException + { + throw new ServletException(); + } + }); + + HttpClient httpClient = new HttpClient(); + httpClient.setProxy(new Address(proxyHost, proxyPort)); + httpClient.registerListener(RedirectListener.class.getName()); + httpClient.start(); + + try + { + ContentExchange exchange = new ContentExchange(true); + exchange.setTimeout(5000); + exchange.setURL("https://www.google.com"); + httpClient.send(exchange); + assertEquals(HttpExchange.STATUS_COMPLETED, exchange.waitForDone()); + assertEquals(200, exchange.getResponseStatus()); + } + finally + { + httpClient.stop(); + } + } + private static class ServerHandler extends AbstractHandler { public void handle(String target, Request request, HttpServletRequest httpRequest, HttpServletResponse httpResponse) throws IOException, ServletException From 06504f2c65be428667cd6bcd73f9500736702957 Mon Sep 17 00:00:00 2001 From: Simone Bordet Date: Thu, 25 Jul 2013 17:20:17 +0200 Subject: [PATCH 2/3] Fixed proxy test. --- .../jetty/client/ProxyFakeTunnelTest.java | 59 +++++++++++-------- 1 file changed, 34 insertions(+), 25 deletions(-) diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/ProxyFakeTunnelTest.java b/jetty-client/src/test/java/org/eclipse/jetty/client/ProxyFakeTunnelTest.java index 236a6b7ff10..eaed5251167 100644 --- a/jetty-client/src/test/java/org/eclipse/jetty/client/ProxyFakeTunnelTest.java +++ b/jetty-client/src/test/java/org/eclipse/jetty/client/ProxyFakeTunnelTest.java @@ -36,12 +36,12 @@ public class ProxyFakeTunnelTest extends ProxyTunnellingTest { return _proxySocket.getLocalPort(); } - + protected void startProxy() throws Exception { _proxySocket = new ServerSocket(0); - + _proxyThread = new Thread() { @Override @@ -63,19 +63,28 @@ public class ProxyFakeTunnelTest extends ProxyTunnellingTest }; _proxyThread.setDaemon(true); _proxyThread.start(); - + } protected void stopProxy() throws Exception { - _proxySocket.close(); - _proxyThread.interrupt(); + if (_proxySocket != null) + { + _proxySocket.close(); + _proxyThread.interrupt(); + } + } + + @Override + public void testExternalProxy() throws Exception + { + // Do not execute this test, since it won't hit the fake proxy } static class FakeProxy extends Thread { Socket _socket; - + public FakeProxy(Socket socket) { _socket=socket; @@ -86,50 +95,50 @@ public class ProxyFakeTunnelTest extends ProxyTunnellingTest Socket toserver=null; final InputStream in; - final OutputStream out; + final OutputStream out; try { in = _socket.getInputStream(); out = _socket.getOutputStream(); - + String address=""; int state=0; - + for (int b=in.read();b>=0;b=in.read()) - { + { switch(state) { case 0: if (' '==b) state=1; break; - + case 1: if (' '==b) state=2; else address+=(char)b; break; - + case 2: if ('\r'==b) state=3; break; - + case 3: if ('\n'==b) state=4; else state=2; break; - + case 4: if ('\r'==b) state=5; else state=2; break; - + case 5: if ('\n'==b) { @@ -142,7 +151,7 @@ public class ProxyFakeTunnelTest extends ProxyTunnellingTest out.write(( "HTTP/1.1 200 OK\r\n"+ "Server: fake\r\n"+ - // "Content-Length: 0\r\n"+ + // "Content-Length: 0\r\n"+ "\r\n" ).getBytes()); } @@ -151,12 +160,12 @@ public class ProxyFakeTunnelTest extends ProxyTunnellingTest out.write(( "HTTP/1.1 503 Unavailable\r\n"+ "Server: fake\r\n"+ - "Content-Length: 0\r\n"+ + "Content-Length: 0\r\n"+ "\r\n" ).getBytes()); } out.flush(); - + if (toserver!=null) { final InputStream from = toserver.getInputStream(); @@ -188,7 +197,7 @@ public class ProxyFakeTunnelTest extends ProxyTunnellingTest copy.setDaemon(true); copy.start(); } - + } else state=2; @@ -196,11 +205,11 @@ public class ProxyFakeTunnelTest extends ProxyTunnellingTest case 6: toserver.getOutputStream().write((byte)b); - + } } - - + + } catch (IOException e) { @@ -221,8 +230,8 @@ public class ProxyFakeTunnelTest extends ProxyTunnellingTest } } } - + } - - + + } From eed3a7fec05b8722f7baec62d272f4f56d56cd1f Mon Sep 17 00:00:00 2001 From: Simone Bordet Date: Thu, 25 Jul 2013 17:36:41 +0200 Subject: [PATCH 3/3] Increase external proxy test timeout. --- .../java/org/eclipse/jetty/client/ProxyTunnellingTest.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/ProxyTunnellingTest.java b/jetty-client/src/test/java/org/eclipse/jetty/client/ProxyTunnellingTest.java index c887d1fb2fa..fd4c1a2d350 100644 --- a/jetty-client/src/test/java/org/eclipse/jetty/client/ProxyTunnellingTest.java +++ b/jetty-client/src/test/java/org/eclipse/jetty/client/ProxyTunnellingTest.java @@ -377,7 +377,8 @@ public class ProxyTunnellingTest try { ContentExchange exchange = new ContentExchange(true); - exchange.setTimeout(5000); + // Use a longer timeout, sometimes the proxy takes a while to answer + exchange.setTimeout(20000); exchange.setURL("https://www.google.com"); httpClient.send(exchange); assertEquals(HttpExchange.STATUS_COMPLETED, exchange.waitForDone());