hc-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From rola...@apache.org
Subject svn commit: r498346 - in /jakarta/httpcomponents/httpclient/trunk/src: examples/org/apache/http/examples/conn/ java/org/apache/http/conn/ java/org/apache/http/conn/impl/
Date Sun, 21 Jan 2007 15:05:07 GMT
Author: rolandw
Date: Sun Jan 21 07:05:06 2007
New Revision: 498346

URL: http://svn.apache.org/viewvc?view=rev&rev=498346
Log:
connection manager, part 3 - SSL via proxy

Added:
    jakarta/httpcomponents/httpclient/trunk/src/examples/org/apache/http/examples/conn/ManagerConnectProxy.java
  (with props)
Modified:
    jakarta/httpcomponents/httpclient/trunk/src/examples/org/apache/http/examples/conn/ManagerConnectDirect.java
    jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/conn/ClientConnectionOperator.java
    jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/conn/ManagedClientConnection.java
    jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/conn/impl/ThreadSafeClientConnManager.java

Modified: jakarta/httpcomponents/httpclient/trunk/src/examples/org/apache/http/examples/conn/ManagerConnectDirect.java
URL: http://svn.apache.org/viewvc/jakarta/httpcomponents/httpclient/trunk/src/examples/org/apache/http/examples/conn/ManagerConnectDirect.java?view=diff&rev=498346&r1=498345&r2=498346
==============================================================================
--- jakarta/httpcomponents/httpclient/trunk/src/examples/org/apache/http/examples/conn/ManagerConnectDirect.java
(original)
+++ jakarta/httpcomponents/httpclient/trunk/src/examples/org/apache/http/examples/conn/ManagerConnectDirect.java
Sun Jan 21 07:05:06 2007
@@ -90,7 +90,6 @@
 
         setup(); // some general setup
 
-        // one operator can be used for many connections
         ClientConnectionManager clcm = createManager();
 
         HttpRequest req = createRequest(target);

Added: jakarta/httpcomponents/httpclient/trunk/src/examples/org/apache/http/examples/conn/ManagerConnectProxy.java
URL: http://svn.apache.org/viewvc/jakarta/httpcomponents/httpclient/trunk/src/examples/org/apache/http/examples/conn/ManagerConnectProxy.java?view=auto&rev=498346
==============================================================================
--- jakarta/httpcomponents/httpclient/trunk/src/examples/org/apache/http/examples/conn/ManagerConnectProxy.java
(added)
+++ jakarta/httpcomponents/httpclient/trunk/src/examples/org/apache/http/examples/conn/ManagerConnectProxy.java
Sun Jan 21 07:05:06 2007
@@ -0,0 +1,271 @@
+/*
+ * $HeadURL$
+ * $Revision$
+ * $Date$
+ *
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package org.apache.http.examples.conn;
+
+
+import org.apache.http.HttpHost;
+import org.apache.http.Header;
+import org.apache.http.HttpRequest;
+import org.apache.http.HttpResponse;
+import org.apache.http.HttpVersion;
+import org.apache.http.message.BasicHttpRequest;
+import org.apache.http.params.HttpParams;
+import org.apache.http.params.HttpProtocolParams;
+import org.apache.http.impl.DefaultHttpParams;
+import org.apache.http.protocol.HttpContext;
+import org.apache.http.protocol.HttpExecutionContext;
+
+import org.apache.http.conn.Scheme;
+import org.apache.http.conn.SocketFactory;
+import org.apache.http.conn.PlainSocketFactory;
+import org.apache.http.conn.ssl.SSLSocketFactory;
+import org.apache.http.conn.HostConfiguration;
+import org.apache.http.conn.ManagedClientConnection;
+import org.apache.http.conn.ClientConnectionManager;
+import org.apache.http.conn.impl.ThreadSafeClientConnManager;
+
+
+
+/**
+ * How to open a secure connection through a proxy using
+ * {@link ClientConnectionManager ClientConnectionManager}.
+ * This exemplifies the <i>opening</i> of the connection only.
+ * The message exchange, both subsequently and for tunnelling,
+ * should not be used as a template.
+ *
+ * @author <a href="mailto:rolandw at apache.org">Roland Weber</a>
+ *
+ *
+ * <!-- empty lines above to avoid 'svn diff' context problems -->
+ * @version $Revision$ $Date$
+ *
+ * @since 4.0
+ */
+public class ManagerConnectProxy {
+
+    /**
+     * The default parameters.
+     * Instantiated in {@link #setup setup}.
+     */
+    private static HttpParams defaultParameters = null;
+
+
+    /**
+     * Main entry point to this example.
+     *
+     * @param args      ignored
+     */
+    public final static void main(String[] args)
+        throws Exception {
+
+        // make sure to use a proxy that supports CONNECT
+        final HttpHost target =
+            new HttpHost("issues.apache.org", 443, "https");
+        final HttpHost proxy =
+            new HttpHost("127.0.0.1", 8666, "http");
+
+        setup(); // some general setup
+
+        ClientConnectionManager clcm = createManager();
+
+        HttpRequest req = createRequest(target);
+        HttpContext ctx = createContext();
+
+        System.out.println("preparing route to " + target + " via " + proxy);
+        HostConfiguration route = new HostConfiguration(target, proxy, null);
+
+        System.out.println("requesting connection for " + route);
+        ManagedClientConnection conn = clcm.getConnection(route);
+        try {
+            System.out.println("opening connection");
+            conn.open(route, ctx, getParams());
+
+            HttpRequest connect = createConnect(target);
+            System.out.println("opening tunnel to " + target);
+            conn.sendRequestHeader(connect);
+            // there is no request entity
+            conn.flush();
+
+            System.out.println("receiving confirmation for tunnel");
+            HttpResponse connected = conn.receiveResponseHeader(getParams());
+            System.out.println("----------------------------------------");
+            printResponseHeader(connected);
+            System.out.println("----------------------------------------");
+            int status = connected.getStatusLine().getStatusCode();
+            if ((status < 200) || (status > 299)) {
+                System.out.println("unexpected status code " + status);
+                System.exit(1);
+            }
+            System.out.println("receiving response body (ignored)");
+            conn.receiveResponseEntity(connected);
+
+            conn.tunnelCreated(false, getParams());
+
+            System.out.println("layering secure connection");
+            conn.layerProtocol(ctx, getParams());
+
+            // finally we have the secure connection and can send the request
+
+            System.out.println("sending request");
+            conn.sendRequestHeader(req);
+            // there is no request entity
+            conn.flush();
+
+            System.out.println("receiving response header");
+            HttpResponse rsp = conn.receiveResponseHeader(getParams());
+
+            System.out.println("----------------------------------------");
+            printResponseHeader(rsp);
+            System.out.println("----------------------------------------");
+
+            System.out.println("closing connection");
+            conn.close();
+
+        } finally {
+
+            if (conn.isOpen()) {
+                System.out.println("shutting down connection");
+                try {
+                    conn.shutdown();
+                } catch (Exception x) {
+                    System.out.println("problem during shutdown");
+                    x.printStackTrace(System.out);
+                }
+            }
+
+            System.out.println("releasing connection");
+            clcm.releaseConnection(conn);
+        }
+
+    } // main
+
+
+    private final static ClientConnectionManager createManager() {
+        return new ThreadSafeClientConnManager(getParams());
+    }
+
+
+    /**
+     * Performs general setup.
+     * This should be called only once.
+     */
+    private final static void setup() {
+
+        // Register the "http" and "https" protocol schemes, they are
+        // required by the default operator to look up socket factories.
+        SocketFactory sf = PlainSocketFactory.getSocketFactory();
+        Scheme.registerScheme("http", new Scheme("http", sf, 80));
+        sf = SSLSocketFactory.getSocketFactory();
+        Scheme.registerScheme("https", new Scheme("https", sf, 80));
+
+        // Prepare parameters.
+        // Since this example doesn't use the full core framework,
+        // only few parameters are actually required.
+        HttpParams params = new DefaultHttpParams();
+        HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
+        HttpProtocolParams.setUseExpectContinue(params, false);
+        defaultParameters = params;
+
+    } // setup
+
+
+    private final static HttpParams getParams() {
+        return defaultParameters;
+    }
+
+
+    /**
+     * Creates a request to tunnel a connection.
+     * In a real application, request interceptors should be used
+     * to add the required headers.
+     *
+     * @param target    the target server for the tunnel
+     *
+     * @return  a CONNECT request without an entity
+     */
+    private final static HttpRequest createConnect(HttpHost target) {
+
+        // see RFC 2817, section 5.2
+        final String authority = target.getHostName()+":"+target.getPort();
+
+        HttpRequest req = new BasicHttpRequest
+            ("CONNECT", authority, HttpVersion.HTTP_1_1);
+
+        req.addHeader("Host", authority);
+
+        return req;
+    }
+
+
+    /**
+     * Creates a request to execute in this example.
+     * In a real application, request interceptors should be used
+     * to add the required headers.
+     *
+     * @param target    the target server for the request
+     *
+     * @return  a request without an entity
+     */
+    private final static HttpRequest createRequest(HttpHost target) {
+
+        HttpRequest req = new BasicHttpRequest
+            ("OPTIONS", "*", HttpVersion.HTTP_1_1);
+
+        req.addHeader("Host", target.getHostName());
+
+        return req;
+    }
+
+
+    /**
+     * Creates a context for executing a request.
+     * Since this example doesn't really use the execution framework,
+     * the context can be left empty.
+     *
+     * @return  a new, empty context
+     */
+    private final static HttpContext createContext() {
+        return new HttpExecutionContext(null);
+    }
+
+
+    private final static void printResponseHeader(HttpResponse rsp) {
+
+        System.out.println(rsp.getStatusLine());
+        Header[] headers = rsp.getAllHeaders();
+        for (int i=0; i<headers.length; i++) {
+            System.out.println(headers[i]);
+        }
+    }
+
+} // class ManagerConnectProxy
+

Propchange: jakarta/httpcomponents/httpclient/trunk/src/examples/org/apache/http/examples/conn/ManagerConnectProxy.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jakarta/httpcomponents/httpclient/trunk/src/examples/org/apache/http/examples/conn/ManagerConnectProxy.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Propchange: jakarta/httpcomponents/httpclient/trunk/src/examples/org/apache/http/examples/conn/ManagerConnectProxy.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/conn/ClientConnectionOperator.java
URL: http://svn.apache.org/viewvc/jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/conn/ClientConnectionOperator.java?view=diff&rev=498346&r1=498345&r2=498346
==============================================================================
--- jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/conn/ClientConnectionOperator.java
(original)
+++ jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/conn/ClientConnectionOperator.java
Sun Jan 21 07:05:06 2007
@@ -86,8 +86,8 @@
      *
      * @param conn      the open connection to update
      * @param target    the target host for the updated connection.
-     *                  The connection must already be open to the
-     *                  host and port, but the scheme of the target
+     *                  The connection must already be open or tunnelled
+     *                  to the host and port, but the scheme of the target
      *                  will be used to create a layered connection.
      * @param context   the context for the connection
      * @param params    the parameters for the updated connection

Modified: jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/conn/ManagedClientConnection.java
URL: http://svn.apache.org/viewvc/jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/conn/ManagedClientConnection.java?view=diff&rev=498346&r1=498345&r2=498346
==============================================================================
--- jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/conn/ManagedClientConnection.java
(original)
+++ jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/conn/ManagedClientConnection.java
Sun Jan 21 07:05:06 2007
@@ -84,14 +84,44 @@
         ;
 
 
-    /* *
-     * Indicates that a tunnel has been created.
+    /**
+     * Indicates that a tunnel 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.
+     * <br/>
+     * <b>Note:</b> In HttpClient 3, a call to the corresponding method
+     * would automatically trigger the layering of the TLS/SSL protocol.
+     * This is not the case anymore, you can establish a tunnel without
+     * layering a new protocol over the connection.
      *
-     * @param route     the route along which the tunnel has been created
-     * @param params    the parameters for updating the connection
+     * @param secure    <code>true</code> if the tunnel should be considered
+     *                  secure, <code>false</code> otherwise
+     * @param params    the parameters for tunnelling this connection
+     *
+     * @throws IOException  in case of a problem
+     */
+    void tunnelCreated(boolean secure, HttpParams params)
+        throws IOException
+        ;
+
+
+    /**
+     * Layers a new protocol on top of a {@link #tunnelCreated tunnelled}
+     * connection. This is typically used to create a TLS/SSL connection
+     * through a proxy.
+     * The route is the one previously passed to {@link #open open}.
+     * It is not guaranteed that the layered connection is
+     * {@link #isSecure secure}.
+     *
+     * @param context   the context for layering on top of this connection
+     * @param params    the parameters for layering on top of this connection
+     *
+     * @throws IOException      in case of a problem
      */
-    //@@@ tunnelCreated in the old implementation triggers layering
-    //@@@ of the TLS/SSL connection. This should be split in two.
+    void layerProtocol(HttpContext context, HttpParams params)
+        throws IOException
+        ;
 
 
     /* *

Modified: jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/conn/impl/ThreadSafeClientConnManager.java
URL: http://svn.apache.org/viewvc/jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/conn/impl/ThreadSafeClientConnManager.java?view=diff&rev=498346&r1=498345&r2=498346
==============================================================================
--- jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/conn/impl/ThreadSafeClientConnManager.java
(original)
+++ jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/conn/impl/ThreadSafeClientConnManager.java
Sun Jan 21 07:05:06 2007
@@ -1096,6 +1096,9 @@
         /** The tunnel created flag part of the tracked route. */
         private boolean tunnelled;
 
+        /** The layered flag part of the tracked route. */
+        private boolean layered;
+
         /** The connection manager. */
         private ThreadSafeClientConnManager manager;
 
@@ -1178,6 +1181,87 @@
 
 
         /**
+         * Tracks tunnelling of the connection.
+         * The tunnel has to be established outside by sending a CONNECT
+         * request to the proxy.
+         *
+         * @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
+         */
+        private void tunnelCreated(boolean secure, HttpParams params)
+            throws IOException {
+
+            if (params == null) {
+                throw new IllegalArgumentException
+                    ("Parameters must not be null.");
+            }
+
+            if (route.getProxyHost() == null) {
+                throw new IllegalStateException("No proxy in route.");
+            }
+            if (tunnelled) {
+                throw new IllegalStateException
+                    ("Connection is already tunnelled.");
+            }
+
+            this.connection.update(null, route.getHost(),
+                                   secure, params);
+            tunnelled = true;
+
+        } // tunnelCreated
+
+
+        /**
+         * Layers a protocol on top of an established tunnel.
+         *
+         * @param context   the context for layering
+         * @param params    the parameters for layering
+         *
+         * @throws IOException  in case of a problem
+         */
+        private void layerProtocol(HttpContext context, HttpParams params)
+            throws IOException {
+
+            //@@@ is context allowed to be null? depends on operator?
+            if (params == null) {
+                throw new IllegalArgumentException
+                    ("Parameters must not be null.");
+            }
+
+            if (!this.tunnelled) {
+                throw new IllegalStateException
+                    ("Protocol layering without a tunnel not supported.");
+            }
+            if (this.layered) {
+                throw new IllegalStateException
+                    ("Protocol already layered.");
+            }
+
+            // - collect the arguments
+            // - call the operator
+            // - update the tracking data
+            // In this order, we can be sure that only a successful
+            // layering on top of the connection will be tracked.
+
+            final HttpHost target = route.getHost();
+
+            if (LOG.isDebugEnabled()) {
+                LOG.debug("Layer protocol on connection to " + target);
+            }
+
+            ThreadSafeClientConnManager.this.connectionOperator
+                .updateSecureConnection(this.connection, target,
+                                        context, params);
+
+            this.layered = true;
+
+        } // layerProtocol
+
+
+        /**
          * Tracks close or shutdown of the connection.
          * There is no distinction between the two, the route is dropped
          * in both cases. This method should be called regardless of
@@ -1235,15 +1319,6 @@
         }
 
         /**
-         * Obtains the wrapped connection.
-         *
-         * @return the wrapped connection
-         */
-        OperatedClientConnection getXWrappedConnection() {
-            return wrappedConnection;
-        }
-
-        /**
          * Detaches this adapter from the wrapped connection.
          * This adapter becomes useless.
          */
@@ -1261,6 +1336,25 @@
             assertAttached();
             poolEntry.open(route, context, params);
         }
+
+
+        // non-javadoc, see interface ManagedHttpConnection
+        public void tunnelCreated(boolean secure, HttpParams params)
+            throws IOException {
+
+            assertAttached();
+            poolEntry.tunnelCreated(secure, params);
+        }
+
+
+        // non-javadoc, see interface ManagedHttpConnection
+        public void layerProtocol(HttpContext context, HttpParams params)
+            throws IOException {
+
+            assertAttached();
+            poolEntry.layerProtocol(context, params);
+        }
+
 
 
         // non-javadoc, see interface HttpConnection        



Mime
View raw message