View Javadoc

    1   /*
    2    * $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//httpclient/src/java/org/apache/commons/httpclient/ConnectMethod.java,v 1.29 2004/06/24 21:39:52 mbecke Exp $
    3    * $Revision: 483949 $
    4    * $Date: 2006-12-08 12:34:50 +0100 (Fri, 08 Dec 2006) $
    5    *
    6    * ====================================================================
    7    *
    8    *  Licensed to the Apache Software Foundation (ASF) under one or more
    9    *  contributor license agreements.  See the NOTICE file distributed with
    10   *  this work for additional information regarding copyright ownership.
    11   *  The ASF licenses this file to You under the Apache License, Version 2.0
    12   *  (the "License"); you may not use this file except in compliance with
    13   *  the License.  You may obtain a copy of the License at
    14   *
    15   *      http://www.apache.org/licenses/LICENSE-2.0
    16   *
    17   *  Unless required by applicable law or agreed to in writing, software
    18   *  distributed under the License is distributed on an "AS IS" BASIS,
    19   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    20   *  See the License for the specific language governing permissions and
    21   *  limitations under the License.
    22   * ====================================================================
    23   *
    24   * This software consists of voluntary contributions made by many
    25   * individuals on behalf of the Apache Software Foundation.  For more
    26   * information on the Apache Software Foundation, please see
    27   * <http://www.apache.org/>.
    28   *
    29   */
    30
    31  package org.apache.commons.httpclient;
    32
    33  import java.io.IOException;
    34
    35  import org.apache.commons.logging.Log;
    36  import org.apache.commons.logging.LogFactory;
    37
    38  /**
    39   * Establishes a tunneled HTTP connection via the CONNECT method.
    40   *
    41   * @author Ortwin Gl???ck
    42   * @author dIon Gillard
    43   * @author <a href="mailto:mbowler@GargoyleSoftware.com">Mike Bowler</a>
    44   * @author <a href="mailto:oleg@ural.ru">Oleg Kalnichevski</a>
    45   * @since 2.0
    46   * @version $Revision: 483949 $ $Date: 2006-12-08 12:34:50 +0100 (Fri, 08 Dec 2006) $
    47   */
    48  public class ConnectMethod extends HttpMethodBase {
    49
    50      /** the name of this method */
    51      public static final String NAME = "CONNECT";
    52
    53      private final HostConfiguration targethost;
    54
    55      /**
    56       * @deprecated use #ConnectMethod(HttpHost);
    57       *
    58       * Create a connect method.
    59       *
    60       * @since 3.0
    61       */
    62      public ConnectMethod() {
    63          super();
    64          this.targethost = null;
    65      }
    66
    67      /**
    68       * @deprecated the wrapped method is no longer used
    69       *
    70       * Create a connect method wrapping the existing method
    71       *
    72       * @param method the {@link HttpMethod method} to execute after connecting
    73       *      to the server
    74       */
    75      public ConnectMethod(HttpMethod method) {
    76          super();
    77          this.targethost = null;
    78      }
    79
    80      /**
    81       * Create a connect method.
    82       *
    83       * @since 3.0
    84       */
    85      public ConnectMethod(final HostConfiguration targethost) {
    86          super();
    87          if (targethost == null) {
    88              throw new IllegalArgumentException("Target host may not be null");
    89          }
    90          this.targethost = targethost;
    91      }
    92
    93      /**
    94       * Provide the {@link #NAME name} of this method.
    95       *
    96       * @return the String "CONNECT"
    97       */
    98      public String getName() {
    99          return NAME;
    100     }
    101
    102     public String getPath() {
    103         if (this.targethost != null) {
    104             StringBuffer buffer = new StringBuffer();
    105             buffer.append(this.targethost.getHost());
    106             int port = this.targethost.getPort();
    107             if (port == -1) {
    108                 port = this.targethost.getProtocol().getDefaultPort();
    109             }
    110             buffer.append(':');
    111             buffer.append(port);
    112             return buffer.toString();
    113         } else {
    114             return "/";
    115         }
    116     }
    117
    118     public URI getURI() throws URIException {
    119         String charset = getParams().getUriCharset();
    120         return new URI(getPath(), true, charset);
    121     }
    122
    123     /**
    124      * This method does nothing. <tt>CONNECT</tt> request is not supposed
    125      * to contain <tt>Cookie</tt> request header.
    126      *
    127      * @param state current state of http requests
    128      * @param conn the connection to use for I/O
    129      *
    130      * @throws IOException when errors occur reading or writing to/from the
    131      *         connection
    132      * @throws HttpException when a recoverable error occurs
    133      *
    134      * @see HttpMethodBase#addCookieRequestHeader(HttpState, HttpConnection)
    135      */
    136     protected void addCookieRequestHeader(HttpState state, HttpConnection conn)
    137         throws IOException, HttpException {
    138         // Do nothing. Not applicable to CONNECT method
    139     }
    140
    141
    142     /**
    143      * Populates the request headers map to with additional {@link Header
    144      * headers} to be submitted to the given {@link HttpConnection}.
    145      *
    146      * <p>
    147      * This implementation adds <tt>User-Agent</tt>, <tt>Host</tt>,
    148      * and <tt>Proxy-Authorization</tt> headers, when appropriate.
    149      * </p>
    150      *
    151      * @param state the client state
    152      * @param conn the {@link HttpConnection} the headers will eventually be
    153      *        written to
    154      * @throws IOException when an error occurs writing the request
    155      * @throws HttpException when a HTTP protocol error occurs
    156      *
    157      * @see #writeRequestHeaders
    158      */
    159     protected void addRequestHeaders(HttpState state, HttpConnection conn)
    160         throws IOException, HttpException {
    161         LOG.trace("enter ConnectMethod.addRequestHeaders(HttpState, "
    162             + "HttpConnection)");
    163         addUserAgentRequestHeader(state, conn);
    164         addHostRequestHeader(state, conn);
    165         addProxyConnectionHeader(state, conn);
    166     }
    167
    168     /**
    169      * Execute this method and create a tunneled HttpConnection.  If the method
    170      * is successful (i.e. the status is a 2xx) tunnelCreated() will be called
    171      * on the connection.
    172      *
    173      * @param state the current http state
    174      * @param conn the connection to write to
    175      * @return the http status code from execution
    176      * @throws HttpException when an error occurs writing the headers
    177      * @throws IOException when an error occurs writing the headers
    178      *
    179      * @see HttpConnection#tunnelCreated()
    180      */
    181     public int execute(HttpState state, HttpConnection conn)
    182     throws IOException, HttpException {
    183
    184         LOG.trace("enter ConnectMethod.execute(HttpState, HttpConnection)");
    185         int code = super.execute(state, conn);
    186         if (LOG.isDebugEnabled()) {
    187             LOG.debug("CONNECT status code " + code);
    188         }
    189         return code;
    190     }
    191
    192     /**
    193      * Special Connect request.
    194      *
    195      * @param state the current http state
    196      * @param conn the connection to write to
    197      * @throws IOException when an error occurs writing the request
    198      * @throws HttpException when an error occurs writing the request
    199      */
    200     protected void writeRequestLine(HttpState state, HttpConnection conn)
    201     throws IOException, HttpException {
    202         StringBuffer buffer = new StringBuffer();
    203         buffer.append(getName());
    204         buffer.append(' ');
    205         if (this.targethost != null) {
    206             buffer.append(getPath());
    207         } else {
    208             int port = conn.getPort();
    209             if (port == -1) {
    210                 port = conn.getProtocol().getDefaultPort();
    211             }
    212             buffer.append(conn.getHost());
    213             buffer.append(':');
    214             buffer.append(port);
    215         }
    216         buffer.append(" ");
    217         buffer.append(getEffectiveVersion());
    218         String line = buffer.toString();
    219         conn.printLine(line, getParams().getHttpElementCharset());
    220         if (Wire.HEADER_WIRE.enabled()) {
    221             Wire.HEADER_WIRE.output(line);
    222         }
    223     }
    224
    225     /**
    226      * Returns <code>true</code> if the status code is anything other than
    227      * SC_OK, <code>false</code> otherwise.
    228      *
    229      * @see HttpMethodBase#shouldCloseConnection(HttpConnection)
    230      * @see HttpStatus#SC_OK
    231      *
    232      * @return <code>true</code> if the connection should be closed
    233      */
    234     protected boolean shouldCloseConnection(HttpConnection conn) {
    235         if (getStatusCode() == HttpStatus.SC_OK) {
    236             Header connectionHeader = null;
    237             if (!conn.isTransparent()) {
    238                 connectionHeader = getResponseHeader("proxy-connection");
    239             }
    240             if (connectionHeader == null) {
    241                 connectionHeader = getResponseHeader("connection");
    242             }
    243             if (connectionHeader != null) {
    244                 if (connectionHeader.getValue().equalsIgnoreCase("close")) {
    245                     if (LOG.isWarnEnabled()) {
    246                         LOG.warn("Invalid header encountered '" + connectionHeader.toExternalForm()
    247                         + "' in response " + getStatusLine().toString());
    248                     }
    249                 }
    250             }
    251             return false;
    252         } else {
    253             return super.shouldCloseConnection(conn);
    254         }
    255     }
    256
    257     /** Log object for this class. */
    258     private static final Log LOG = LogFactory.getLog(ConnectMethod.class);
    259
    260 }