You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hc.apache.org by ro...@apache.org on 2007/09/08 16:20:54 UTC

svn commit: r573844 - in /jakarta/httpcomponents/httpclient/trunk: ./ module-client/src/main/java/org/apache/http/conn/ module-client/src/main/java/org/apache/http/impl/client/ module-client/src/main/java/org/apache/http/impl/conn/ module-client/src/te...

Author: rolandw
Date: Sat Sep  8 07:20:53 2007
New Revision: 573844

URL: http://svn.apache.org/viewvc?rev=573844&view=rev
Log:
HTTPCLIENT-649: ManagedClientConnection now supports proxy chains

Modified:
    jakarta/httpcomponents/httpclient/trunk/RELEASE_NOTES.txt
    jakarta/httpcomponents/httpclient/trunk/module-client/src/main/java/org/apache/http/conn/ManagedClientConnection.java
    jakarta/httpcomponents/httpclient/trunk/module-client/src/main/java/org/apache/http/impl/client/DefaultClientRequestDirector.java
    jakarta/httpcomponents/httpclient/trunk/module-client/src/main/java/org/apache/http/impl/conn/AbstractPoolEntry.java
    jakarta/httpcomponents/httpclient/trunk/module-client/src/main/java/org/apache/http/impl/conn/AbstractPooledConnAdapter.java
    jakarta/httpcomponents/httpclient/trunk/module-client/src/test/java/org/apache/http/impl/conn/ClientConnAdapterMockup.java

Modified: jakarta/httpcomponents/httpclient/trunk/RELEASE_NOTES.txt
URL: http://svn.apache.org/viewvc/jakarta/httpcomponents/httpclient/trunk/RELEASE_NOTES.txt?rev=573844&r1=573843&r2=573844&view=diff
==============================================================================
--- jakarta/httpcomponents/httpclient/trunk/RELEASE_NOTES.txt (original)
+++ jakarta/httpcomponents/httpclient/trunk/RELEASE_NOTES.txt Sat Sep  8 07:20:53 2007
@@ -1,5 +1,8 @@
 Changes since release 4.0 Alpha 1
 
+* [HTTPCLIENT-649] support for proxy chains in HttpConn
+  Contributed by Roland Weber <rolandw at apache.org>
+
 * [HTTPCLIENT-636] refactor ThreadSafeClientConnManager in separate package
   Contributed by Roland Weber <rolandw at apache.org>
 

Modified: jakarta/httpcomponents/httpclient/trunk/module-client/src/main/java/org/apache/http/conn/ManagedClientConnection.java
URL: http://svn.apache.org/viewvc/jakarta/httpcomponents/httpclient/trunk/module-client/src/main/java/org/apache/http/conn/ManagedClientConnection.java?rev=573844&r1=573843&r2=573844&view=diff
==============================================================================
--- jakarta/httpcomponents/httpclient/trunk/module-client/src/main/java/org/apache/http/conn/ManagedClientConnection.java (original)
+++ jakarta/httpcomponents/httpclient/trunk/module-client/src/main/java/org/apache/http/conn/ManagedClientConnection.java Sat Sep  8 07:20:53 2007
@@ -35,6 +35,7 @@
 
 import org.apache.http.HttpClientConnection;
 import org.apache.http.HttpInetConnection;
+import org.apache.http.HttpHost;
 import org.apache.http.params.HttpParams;
 import org.apache.http.protocol.HttpContext;
 
@@ -80,8 +81,8 @@
     /**
      * Opens this connection according to the given route.
      *
-     * @param route     the route along which to open. It will be opened
-     *                  to the proxy if present, or directly to the target.
+     * @param route     the route along which to open. It will be opened to
+     *                  the first proxy if present, or directly to the target.
      * @param context   the context for opening this connection
      * @param params    the parameters for opening this connection
      *
@@ -93,7 +94,7 @@
 
 
     /**
-     * Indicates that a tunnel has been established.
+     * Indicates that a tunnel to the target has been established.
      * The route is the one previously passed to {@link #open open}.
      * Subsequently, {@link #layerProtocol layerProtocol} can be called
      * to layer the TLS/SSL protocol on top of the tunnelled connection.
@@ -109,7 +110,32 @@
      *
      * @throws IOException  in case of a problem
      */
-    void tunnelCreated(boolean secure, HttpParams params)
+    void tunnelTarget(boolean secure, HttpParams params)
+        throws IOException
+        ;
+
+
+    /**
+     * Indicates that a tunnel to an intermediate proxy has been established.
+     * This is used exclusively for so-called <i>proxy chains</i>, where
+     * a request has to pass through multiple proxies before reaching the
+     * target. In that case, all proxies but the last need to be tunnelled
+     * when establishing the connection. Tunnelling of the last proxy to the
+     * target is optional and would be indicated via {@link #tunnelTarget}.
+     *
+     * @param next      the proxy to which the tunnel was established.
+     *                  This is <i>not</i> the proxy <i>through</i> which
+     *                  the tunnel was established, but the new end point
+     *                  of the tunnel. The tunnel does <i>not</i> yet
+     *                  reach to the target, use {@link #tunnelTarget}
+     *                  to indicate an end-to-end tunnel.
+     * @param secure    <code>true</code> if the connection should be
+     *                  considered secure, <code>false</code> otherwise
+     * @param params    the parameters for tunnelling this connection
+     *
+     * @throws IOException  in case of a problem
+     */
+    void tunnelProxy(HttpHost next, boolean secure, HttpParams params)
         throws IOException
         ;
 

Modified: jakarta/httpcomponents/httpclient/trunk/module-client/src/main/java/org/apache/http/impl/client/DefaultClientRequestDirector.java
URL: http://svn.apache.org/viewvc/jakarta/httpcomponents/httpclient/trunk/module-client/src/main/java/org/apache/http/impl/client/DefaultClientRequestDirector.java?rev=573844&r1=573843&r2=573844&view=diff
==============================================================================
--- jakarta/httpcomponents/httpclient/trunk/module-client/src/main/java/org/apache/http/impl/client/DefaultClientRequestDirector.java (original)
+++ jakarta/httpcomponents/httpclient/trunk/module-client/src/main/java/org/apache/http/impl/client/DefaultClientRequestDirector.java Sat Sep  8 07:20:53 2007
@@ -439,7 +439,8 @@
      *
      * @throws HttpException    in case of a problem
      */
-    protected ManagedClientConnection allocateConnection(HttpRoute route, long timeout)
+    protected ManagedClientConnection allocateConnection(HttpRoute route,
+                                                         long timeout)
         throws HttpException, ConnectionPoolTimeoutException {
 
         return connManager.getConnection(route, timeout);
@@ -481,15 +482,24 @@
                 managedConn.open(route, context, this.params);
                 break;
 
-            case HttpRouteDirector.TUNNEL_TARGET:
-                boolean secure = createTunnel(route, context);
-                LOG.debug("Tunnel created");
-                managedConn.tunnelCreated(secure, this.params);
-                break;
+            case HttpRouteDirector.TUNNEL_TARGET: {
+                boolean secure = createTunnelToTarget(route, context);
+                LOG.debug("Tunnel to target created.");
+                managedConn.tunnelTarget(secure, this.params);
+            }   break;
+
+            case HttpRouteDirector.TUNNEL_PROXY: {
+                // The most simple example for this case is a proxy chain
+                // of two proxies, where P1 must be tunnelled to P2.
+                // route: Source -> P1 -> P2 -> Target (3 hops)
+                // fact:  Source -> P1 -> Target       (2 hops)
+                final int hop = fact.getHopCount()-1; // the hop to establish
+                boolean secure = createTunnelToProxy(route, hop, context);
+                LOG.debug("Tunnel to proxy created.");
+                managedConn.tunnelProxy(route.getHopTarget(hop),
+                                        secure, this.params);
+            }   break;
 
-            case HttpRouteDirector.TUNNEL_PROXY:
-                throw new UnsupportedOperationException
-                    ("Proxy chains are not supported.");
 
             case HttpRouteDirector.LAYER_PROTOCOL:
                 managedConn.layerProtocol(context, this.params);
@@ -516,8 +526,8 @@
 
 
     /**
-     * Creates a tunnel.
-     * The connection must be established to the proxy.
+     * Creates a tunnel to the target server.
+     * The connection must be established to the (last) proxy.
      * A CONNECT request for tunnelling through the proxy will
      * be created and sent, the response received and checked.
      * This method does <i>not</i> update the connection with
@@ -534,7 +544,8 @@
      * @throws HttpException    in case of a problem
      * @throws IOException      in case of an IO problem
      */
-    protected boolean createTunnel(HttpRoute route, HttpContext context)
+    protected boolean createTunnelToTarget(HttpRoute route,
+                                           HttpContext context)
         throws HttpException, IOException {
 
         HttpHost proxy = route.getProxyHost();
@@ -645,7 +656,45 @@
         // Even if that is secure, the hop to the target may be insecure.
         // Leave it to derived classes, consider insecure by default here.
         return false;
+
+    } // createTunnelToTarget
+
+
+
+    /**
+     * Creates a tunnel to an intermediate proxy.
+     * This method is <i>not</i> implemented in this class.
+     * It just throws an exception here.
+     *
+     * @param route     the route to establish
+     * @param hop       the hop in the route to establish now.
+     *                  <code>route.getHopTarget(hop)</code>
+     *                  will return the proxy to tunnel to.
+     * @param context   the context for request execution
+     *
+     * @return  <code>true</code> if the partially tunnelled connection
+     *          is secure, <code>false</code> otherwise.
+     *
+     * @throws HttpException    in case of a problem
+     * @throws IOException      in case of an IO problem
+     */
+    protected boolean createTunnelToProxy(HttpRoute route, int hop,
+                                          HttpContext context)
+        throws HttpException, IOException {
+
+        // Have a look at createTunnelToTarget and replicate the parts
+        // you need in a custom derived class. If your proxies don't require
+        // authentication, it is not too hard. But for the stock version of
+        // HttpClient, we cannot make such simplifying assumptions and would
+        // have to include proxy authentication code. The HttpComponents team
+        // is currently not in a position to support rarely used code of this
+        // complexity. Feel free to submit patches that refactor the code in
+        // createTunnelToTarget to facilitate re-use for proxy tunnelling.
+
+        throw new UnsupportedOperationException
+            ("Proxy chains are not supported.");
     }
+
 
 
     /**

Modified: jakarta/httpcomponents/httpclient/trunk/module-client/src/main/java/org/apache/http/impl/conn/AbstractPoolEntry.java
URL: http://svn.apache.org/viewvc/jakarta/httpcomponents/httpclient/trunk/module-client/src/main/java/org/apache/http/impl/conn/AbstractPoolEntry.java?rev=573844&r1=573843&r2=573844&view=diff
==============================================================================
--- jakarta/httpcomponents/httpclient/trunk/module-client/src/main/java/org/apache/http/impl/conn/AbstractPoolEntry.java (original)
+++ jakarta/httpcomponents/httpclient/trunk/module-client/src/main/java/org/apache/http/impl/conn/AbstractPoolEntry.java Sat Sep  8 07:20:53 2007
@@ -161,9 +161,9 @@
 
 
     /**
-     * Tracks tunnelling of the connection.
+     * Tracks tunnelling of the connection to the target.
      * The tunnel has to be established outside by sending a CONNECT
-     * request to the proxy.
+     * request to the (last) proxy.
      *
      * @param secure    <code>true</code> if the tunnel should be
      *                  considered secure, <code>false</code> otherwise
@@ -171,7 +171,7 @@
      *
      * @throws IOException  in case of a problem
      */
-    public void tunnelCreated(boolean secure, HttpParams params)
+    public void tunnelTarget(boolean secure, HttpParams params)
         throws IOException {
 
         if (params == null) {
@@ -194,7 +194,47 @@
                                secure, params);
         this.tracker.tunnelTarget(secure);
 
-    } // tunnelCreated
+    } // tunnelTarget
+
+
+    /**
+     * Tracks tunnelling of the connection to a chained proxy.
+     * The tunnel has to be established outside by sending a CONNECT
+     * request to the previous proxy.
+     *
+     * @param next      the proxy to which the tunnel was established.
+     *  See {@link org.apache.http.conn.ManagedClientConnection#tunnelProxy
+     *                                  ManagedClientConnection.tunnelProxy}
+     *                  for details.
+     * @param secure    <code>true</code> if the tunnel should be
+     *                  considered secure, <code>false</code> otherwise
+     * @param params    the parameters for tunnelling the connection
+     *
+     * @throws IOException  in case of a problem
+     */
+    public void tunnelProxy(HttpHost next, boolean secure, HttpParams params)
+        throws IOException {
+
+        if (next == null) {
+            throw new IllegalArgumentException
+                ("Next proxy must not be null.");
+        }
+        if (params == null) {
+            throw new IllegalArgumentException
+                ("Parameters must not be null.");
+        }
+
+        //@@@ check for proxy in planned route?
+        if ((this.tracker == null) || !this.tracker.isConnected()) {
+            throw new IllegalStateException("Connection not open.");
+        }
+
+        // LOG.debug?
+
+        this.connection.update(null, next, secure, params);
+        this.tracker.tunnelProxy(next, secure);
+
+    } // tunnelProxy
 
 
     /**

Modified: jakarta/httpcomponents/httpclient/trunk/module-client/src/main/java/org/apache/http/impl/conn/AbstractPooledConnAdapter.java
URL: http://svn.apache.org/viewvc/jakarta/httpcomponents/httpclient/trunk/module-client/src/main/java/org/apache/http/impl/conn/AbstractPooledConnAdapter.java?rev=573844&r1=573843&r2=573844&view=diff
==============================================================================
--- jakarta/httpcomponents/httpclient/trunk/module-client/src/main/java/org/apache/http/impl/conn/AbstractPooledConnAdapter.java (original)
+++ jakarta/httpcomponents/httpclient/trunk/module-client/src/main/java/org/apache/http/impl/conn/AbstractPooledConnAdapter.java Sat Sep  8 07:20:53 2007
@@ -33,6 +33,7 @@
 
 import java.io.IOException;
 
+import org.apache.http.HttpHost;
 import org.apache.http.params.HttpParams;
 import org.apache.http.protocol.HttpContext;
 import org.apache.http.conn.HttpRoute;
@@ -122,11 +123,20 @@
 
 
     // non-javadoc, see interface ManagedHttpConnection
-    public void tunnelCreated(boolean secure, HttpParams params)
+    public void tunnelTarget(boolean secure, HttpParams params)
         throws IOException {
 
         assertAttached();
-        poolEntry.tunnelCreated(secure, params);
+        poolEntry.tunnelTarget(secure, params);
+    }
+
+
+    // non-javadoc, see interface ManagedHttpConnection
+    public void tunnelProxy(HttpHost next, boolean secure, HttpParams params)
+        throws IOException {
+
+        assertAttached();
+        poolEntry.tunnelProxy(next, secure, params);
     }
 
 

Modified: jakarta/httpcomponents/httpclient/trunk/module-client/src/test/java/org/apache/http/impl/conn/ClientConnAdapterMockup.java
URL: http://svn.apache.org/viewvc/jakarta/httpcomponents/httpclient/trunk/module-client/src/test/java/org/apache/http/impl/conn/ClientConnAdapterMockup.java?rev=573844&r1=573843&r2=573844&view=diff
==============================================================================
--- jakarta/httpcomponents/httpclient/trunk/module-client/src/test/java/org/apache/http/impl/conn/ClientConnAdapterMockup.java (original)
+++ jakarta/httpcomponents/httpclient/trunk/module-client/src/test/java/org/apache/http/impl/conn/ClientConnAdapterMockup.java Sat Sep  8 07:20:53 2007
@@ -30,6 +30,7 @@
 
 package org.apache.http.impl.conn;
 
+import org.apache.http.HttpHost;
 import org.apache.http.conn.HttpRoute;
 import org.apache.http.params.HttpParams;
 import org.apache.http.protocol.HttpContext;
@@ -64,7 +65,11 @@
         throw new UnsupportedOperationException("just a mockup");
     }
 
-    public void tunnelCreated(boolean secure, HttpParams params) {
+    public void tunnelTarget(boolean secure, HttpParams params) {
+        throw new UnsupportedOperationException("just a mockup");
+    }
+
+    public void tunnelProxy(HttpHost next, boolean secure, HttpParams params) {
         throw new UnsupportedOperationException("just a mockup");
     }