Return-Path: Delivered-To: apmail-jakarta-httpcomponents-commits-archive@www.apache.org Received: (qmail 68041 invoked from network); 5 Jan 2007 17:58:09 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (140.211.11.2) by minotaur.apache.org with SMTP; 5 Jan 2007 17:58:09 -0000 Received: (qmail 40403 invoked by uid 500); 5 Jan 2007 17:58:16 -0000 Delivered-To: apmail-jakarta-httpcomponents-commits-archive@jakarta.apache.org Received: (qmail 40381 invoked by uid 500); 5 Jan 2007 17:58:15 -0000 Mailing-List: contact httpcomponents-commits-help@jakarta.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: httpcomponents-dev@jakarta.apache.org Delivered-To: mailing list httpcomponents-commits@jakarta.apache.org Received: (qmail 40372 invoked by uid 99); 5 Jan 2007 17:58:15 -0000 Received: from herse.apache.org (HELO herse.apache.org) (140.211.11.133) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 05 Jan 2007 09:58:15 -0800 X-ASF-Spam-Status: No, hits=-9.4 required=10.0 tests=ALL_TRUSTED,NO_REAL_NAME X-Spam-Check-By: apache.org Received: from [140.211.11.3] (HELO eris.apache.org) (140.211.11.3) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 05 Jan 2007 09:57:31 -0800 Received: by eris.apache.org (Postfix, from userid 65534) id 478A31A981A; Fri, 5 Jan 2007 09:56:09 -0800 (PST) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r493102 - in /jakarta/httpcomponents/httpclient/trunk/src: examples/org/apache/http/examples/conn/OperatorConnectProxy.java java/org/apache/http/conn/ssl/SSLSocketFactory.java Date: Fri, 05 Jan 2007 17:56:08 -0000 To: httpcomponents-commits@jakarta.apache.org From: rolandw@apache.org X-Mailer: svnmailer-1.1.0 Message-Id: <20070105175609.478A31A981A@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Author: rolandw Date: Fri Jan 5 09:56:06 2007 New Revision: 493102 URL: http://svn.apache.org/viewvc?view=rev&rev=493102 Log: new connection interfaces, step 5 - example for SSL tunnelling through proxy Added: jakarta/httpcomponents/httpclient/trunk/src/examples/org/apache/http/examples/conn/OperatorConnectProxy.java (with props) Modified: jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/conn/ssl/SSLSocketFactory.java Added: jakarta/httpcomponents/httpclient/trunk/src/examples/org/apache/http/examples/conn/OperatorConnectProxy.java URL: http://svn.apache.org/viewvc/jakarta/httpcomponents/httpclient/trunk/src/examples/org/apache/http/examples/conn/OperatorConnectProxy.java?view=auto&rev=493102 ============================================================================== --- jakarta/httpcomponents/httpclient/trunk/src/examples/org/apache/http/examples/conn/OperatorConnectProxy.java (added) +++ jakarta/httpcomponents/httpclient/trunk/src/examples/org/apache/http/examples/conn/OperatorConnectProxy.java Fri Jan 5 09:56:06 2007 @@ -0,0 +1,260 @@ +/* + * $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 + * . + * + */ + +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.UnmanagedClientConnection; +import org.apache.http.conn.SocketConnectionOperator; +import org.apache.http.conn.impl.DefaultClientConnection; +import org.apache.http.conn.impl.DefaultSocketConnectionOperator; + + + +/** + * How to open a secure connection through a proxy using + * {@link SocketConnectionOperator SocketConnectionOperator}. + * This exemplifies the opening of the connection only. + * The message exchange, both subsequently and for tunnelling, + * should not be used as a template. + * + * @author Roland Weber + * + * + * + * @version $Revision$ $Date$ + * + * @since 4.0 + */ +public class OperatorConnectProxy { + + /** + * 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 + + // one operator can be used for many connections + SocketConnectionOperator scop = createOperator(); + UnmanagedClientConnection conn = createConnection(); + + HttpRequest req = createRequest(target); + HttpContext ctx = createContext(); + + System.out.println("opening connection to " + proxy); + scop.openConnection(conn, proxy, 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); + + // Now we have a tunnel to the target. As we will be creating a + // layered TLS/SSL socket immediately afterwards, updating the + // connection with the new target is optional - but good style. + // The scheme part of the target is already "https", though the + // connection is not yet switched to the TLS/SSL protocol. + conn.update(null, target, false, getParams()); + + System.out.println("layering secure connection"); + scop.updateSecureConnection(conn, target, 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(); + + } // main + + + private final static SocketConnectionOperator createOperator() { + return new DefaultSocketConnectionOperator(); + } + + private final static UnmanagedClientConnection createConnection() { + return new DefaultClientConnection(); + } + + + /** + * 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