You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@commons.apache.org by mb...@apache.org on 2004/04/13 04:08:30 UTC

cvs commit: jakarta-commons/httpclient/src/examples ProxyTunnelDemo.java

mbecke      2004/04/12 19:08:30

  Modified:    httpclient/src/java/org/apache/commons/httpclient
                        HttpConnection.java
  Added:       httpclient/src/java/org/apache/commons/httpclient
                        ProxyClient.java
               httpclient/src/examples ProxyTunnelDemo.java
  Log:
  Adds stand-alone support for tunneled HTTP proxies via the ProxyClient.
  
  PR: 28151
  Submitted by: Michael Becke
  Reviewed by: Oleg Kalnichevski
  
  Revision  Changes    Path
  1.86      +14 -5     jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/HttpConnection.java
  
  Index: HttpConnection.java
  ===================================================================
  RCS file: /home/cvs/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/HttpConnection.java,v
  retrieving revision 1.85
  retrieving revision 1.86
  diff -u -r1.85 -r1.86
  --- HttpConnection.java	22 Feb 2004 18:08:45 -0000	1.85
  +++ HttpConnection.java	13 Apr 2004 02:08:30 -0000	1.86
  @@ -82,7 +82,7 @@
    *
    * @author Rod Waldhoff
    * @author Sean C. Sullivan
  - * @author Ortwin Glück
  + * @author Ortwin Gl??ck
    * @author <a href="mailto:jsdever@apache.org">Jeff Dever</a>
    * @author <a href="mailto:mbowler@GargoyleSoftware.com">Mike Bowler</a>
    * @author <a href="mailto:oleg@ural.ru">Oleg Kalnichevski</a>
  @@ -199,6 +199,15 @@
       }
   
       // ------------------------------------------ Attribute Setters and Getters
  +
  +    /**
  +     * Returns the connection socket.
  +     *
  +     * @return the socket.
  +     */
  +    protected Socket getSocket() {
  +        return this.socket;
  +    }
   
       /**
        * Returns the host.
  
  
  
  1.1                  jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/ProxyClient.java
  
  Index: ProxyClient.java
  ===================================================================
  /*
   * $Header: /home/cvs/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/ProxyClient.java,v 1.1 2004/04/13 02:08:30 mbecke Exp $
   * $Revision: 1.1 $
   * $Date: 2004/04/13 02:08:30 $
   *
   * ====================================================================
   *
   *  Copyright 1999-2004 The Apache Software Foundation
   *
   *  Licensed 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/>.
   *
   * [Additional notices, if required by prior licensing conditions]
   *
   */
  
  package org.apache.commons.httpclient;
  
  import java.io.IOException;
  import java.net.Socket;
  
  import org.apache.commons.httpclient.params.HttpClientParams;
  import org.apache.commons.httpclient.params.HttpConnectionManagerParams;
  import org.apache.commons.httpclient.params.HttpParams;
  
  
  /**
   * A client that provides {@link java.net.Socket sockets} for communicating through HTTP proxies
   * via the HTTP CONNECT method.  This is primarily needed for non-HTTP protocols that wish to 
   * communicate via an HTTP proxy.
   * 
   * @author <a href="mailto:oleg@ural.ru">Oleg Kalnichevski</a>
   * @author Michael Becke
   * 
   * @since 3.0
   * 
   * @version $Revision: 1.1 $
   */
  public class ProxyClient {
  
      // ----------------------------------------------------- Instance Variables
  
      /**
       * The {@link HttpState HTTP state} associated with this ProxyClient.
       */
      private HttpState state = new HttpState();
      
      /**
       * The {@link HttpClientParams collection of parameters} associated with this ProxyClient.
       */
      private HttpClientParams params = null; 
  
      /** 
       * The {@link HostConfiguration host configuration} associated with
       * the ProxyClient
       */
      private HostConfiguration hostConfiguration = new HostConfiguration();
      
      /**
       * Creates an instance of ProxyClient using default {@link HttpClientParams parameter set}.
       * 
       * @see HttpClientParams
       */
      public ProxyClient() {
          this(new HttpClientParams());
      }
  
      /**
       * Creates an instance of ProxyClient using the given 
       * {@link HttpClientParams parameter set}.
       * 
       * @param params The {@link HttpClientParams parameters} to use.
       * 
       * @see HttpClientParams
       */
      public ProxyClient(HttpClientParams params) {
          super();
          if (params == null) {
              throw new IllegalArgumentException("Params may not be null");  
          }
          this.params = params;
      }
  
      // ------------------------------------------------------------- Properties
  
      /**
       * Returns {@link HttpState HTTP state} associated with the ProxyClient.
       *
       * @see #setState(HttpState)
       * @return the shared client state
       */
      public synchronized HttpState getState() {
          return state;
      }
  
      /**
       * Assigns {@link HttpState HTTP state} for the ProxyClient.
       *
       * @see #getState()
       * @param state the new {@link HttpState HTTP state} for the client
       */
      public synchronized void setState(HttpState state) {
          this.state = state;
      }
  
      /**
       * Returns the {@link HostConfiguration host configuration} associated with the 
       * ProxyClient.
       * 
       * @return {@link HostConfiguration host configuration}
       */
      public synchronized HostConfiguration getHostConfiguration() {
          return hostConfiguration;
      }
  
      /**
       * Assigns the {@link HostConfiguration host configuration} to use with the
       * ProxyClient.
       * 
       * @param hostConfiguration The {@link HostConfiguration host configuration} to set
       */
      public synchronized void setHostConfiguration(HostConfiguration hostConfiguration) {
          this.hostConfiguration = hostConfiguration;
      }
  
      /**
       * Returns {@link HttpClientParams HTTP protocol parameters} associated with this ProxyClient.
       * 
       * @see HttpClientParams
       */
      public synchronized HttpClientParams getParams() {
          return this.params;
      }
  
      /**
       * Assigns {@link HttpClientParams HTTP protocol parameters} for this ProxyClient.
       * 
       * @see HttpClientParams
       */
      public synchronized void setParams(final HttpClientParams params) {
          if (params == null) {
              throw new IllegalArgumentException("Parameters may not be null");
          }
          this.params = params;
      }
  
      /**
       * Creates a socket that is connected, via the HTTP CONNECT method, to a proxy.
       * 
       * <p>
       * Even though HTTP CONNECT proxying is generally used for HTTPS tunneling, the returned
       * socket will not have been wrapped in an SSL socket.
       * </p>
       * 
       * <p>
       * Both the proxy and destination hosts must be set via the 
       * {@link #getHostConfiguration() host configuration} prior to calling this method.
       * </p>
       * 
       * @return the connect response
       * 
       * @throws IOException
       * @throws HttpException
       * 
       * @see #getHostConfiguration()
       */
      public ConnectResponse connect() throws IOException, HttpException {
          
          if (!getHostConfiguration().isProxySet()) {
              throw new IllegalStateException("proxy host must be configured");
          }
          if (!getHostConfiguration().isHostSet()) {
              throw new IllegalStateException("destination host must be configured");
          }
          
          ConnectMethod method = new ConnectMethod();
          method.getParams().setDefaults(getParams());
          
          DummyConnectionManager connectionManager = new DummyConnectionManager();
          connectionManager.setConnectionParams(getParams());
          
          HttpMethodDirector director = new HttpMethodDirector(
              connectionManager,
              getHostConfiguration(),
              getParams(),
              getState()
          );
          
          director.executeMethod(method);
          
          ConnectResponse response = new ConnectResponse();
          response.setConnectMethod(method);
          
          // only set the socket if the connect was successful
          if (method.getStatusCode() == HttpStatus.SC_OK) {
              response.setSocket(connectionManager.getConnection().getSocket());
          } else {
              connectionManager.getConnection().close();
          }
          
          return response;
      }
  
      /**
       * Contains the method used to execute the connect along with the created socket.
       */
      public static class ConnectResponse {
          
          private ConnectMethod connectMethod;
          
          private Socket socket;
          
          private ConnectResponse() {}
          
          /**
           * Gets the method that was used to execute the connect.  This method is useful for 
           * analyzing the proxy's response when a connect fails.
           * 
           * @return the connectMethod.
           */
          public ConnectMethod getConnectMethod() {
              return connectMethod;
          }
          /**
           * @param connectMethod The connectMethod to set.
           */
          private void setConnectMethod(ConnectMethod connectMethod) {
              this.connectMethod = connectMethod;
          }
          /**
           * Gets the socket connected and authenticated (if appropriate) to the configured
           * HTTP proxy, or <code>null</code> if a connection could not be made.  It is the
           * responsibility of the user to close this socket when it is no longer needed.
           * 
           * @return the socket.
           */
          public Socket getSocket() {
              return socket;
          }
          /**
           * @param socket The socket to set.
           */
          private void setSocket(Socket socket) {
              this.socket = socket;
          }
      }
      
      /**
       * A connection manager that creates a single connection.  Meant to be used only once.
       */
      class DummyConnectionManager implements HttpConnectionManager {
  
          private HttpConnection httpConnection;
          
          private HttpParams connectionParams;
          
          public HttpConnection getConnection() {
              return httpConnection;
          }
  
          public void setConnectionParams(HttpParams httpParams) {
              this.connectionParams = httpParams;
          }
  
          public HttpConnection getConnectionWithTimeout(
              HostConfiguration hostConfiguration, long timeout) {
  
              httpConnection = new HttpConnection(hostConfiguration);
              httpConnection.setHttpConnectionManager(this);
              httpConnection.getParams().setDefaults(connectionParams);
              return httpConnection;
          }        
          
          public HttpConnection getConnection(HostConfiguration hostConfiguration, long timeout)
              throws HttpException {
              return getConnectionWithTimeout(hostConfiguration, timeout);
          }
          
          public HttpConnection getConnection(HostConfiguration hostConfiguration) {
              return getConnectionWithTimeout(hostConfiguration, -1);
          }
      
          public void releaseConnection(HttpConnection conn) {
          }
  
          public HttpConnectionManagerParams getParams() {
              return null;
          }
  
          public void setParams(HttpConnectionManagerParams params) {
          }
      }
  }
  
  
  
  1.1                  jakarta-commons/httpclient/src/examples/ProxyTunnelDemo.java
  
  Index: ProxyTunnelDemo.java
  ===================================================================
  import java.io.BufferedReader;
  import java.io.InputStreamReader;
  import java.io.OutputStreamWriter;
  import java.io.Writer;
  import java.net.Socket;
  
  import org.apache.commons.httpclient.ProxyClient;
  import org.apache.commons.httpclient.UsernamePasswordCredentials;
  import org.apache.commons.httpclient.auth.HttpAuthRealm;
  
  /*
   * $Header: /home/cvs/jakarta-commons/httpclient/src/examples/ProxyTunnelDemo.java,v 1.1 2004/04/13 02:08:30 mbecke Exp $
   * $Revision: 1.1 $
   * $Date: 2004/04/13 02:08:30 $
   * ====================================================================
   *
   *  Copyright 2002-2004 The Apache Software Foundation
   *
   *  Licensed 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/>.
   *
   * [Additional notices, if required by prior licensing conditions]
   *
   */
  
  /**
   * Example code for using {@link org.apache.commons.httpclient.ProxyClient}.
   * 
   * @author Oleg Kalnichevski
   * @author Michael Becke
   */
  public class ProxyTunnelDemo {
  
      public static void main(String[] args) throws Exception {
          
          ProxyClient proxyclient = new ProxyClient();
          // set the host the proxy should create a connection to
          //
          // Note:  By default port 80 will be used. Some proxies only allow conections
          // to ports 443 and 8443.  This is because the HTTP CONNECT method was intented
          // to be used for tunneling HTTPS.
          proxyclient.getHostConfiguration().setHost("www.yahoo.com");
          // set the proxy host and port
          proxyclient.getHostConfiguration().setProxy("10.0.1.1", 3128);
          // set the proxy credentials, only necessary for authenticating proxies
          proxyclient.getState().setProxyCredentials(
              new HttpAuthRealm("10.0.1.1", 3128, null),
              new UsernamePasswordCredentials("proxy", "proxy"));
          
          // create the socket
          ProxyClient.ConnectResponse response = proxyclient.connect(); 
          
          if (response.getSocket() != null) {
              Socket socket = response.getSocket();
              try {
                  // go ahead and do an HTTP GET using the socket
                  Writer out = new OutputStreamWriter(
                      socket.getOutputStream(), "ISO-8859-1");
                  out.write("GET http://www.yahoo.com/ HTTP/1.1\r\n");  
                  out.write("Host: www.yahoo.com\r\n");  
                  out.write("Agent: whatever\r\n");  
                  out.write("\r\n");  
                  out.flush();  
                  BufferedReader in = new BufferedReader(
                      new InputStreamReader(socket.getInputStream(), "ISO-8859-1"));
                  String line = null;
                  while ((line = in.readLine()) != null) {
                      System.out.println(line);
                  }
              } finally {
                  // be sure to close the socket when we're done
                  socket.close(); 
              }
          } else {
              // the proxy connect was not successful, check connect method for reasons why
              System.out.println("Connect failed: " + response.getConnectMethod().getStatusLine());
              System.out.println(response.getConnectMethod().getResponseBodyAsString());
          }
      }
          
  }
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-dev-help@jakarta.apache.org