commons-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ol...@apache.org
Subject cvs commit: jakarta-commons/httpclient/src/java/org/apache/commons/httpclient ConnectMethod.java HttpConnection.java HttpMethodBase.java
Date Fri, 25 Apr 2003 18:03:29 GMT
olegk       2003/04/25 11:03:29

  Modified:    httpclient/src/java/org/apache/commons/httpclient
                        ConnectMethod.java HttpConnection.java
                        HttpMethodBase.java
  Log:
  Bug fix #19250 (The PostMethod did not bring back response headers from proxy servers)
  Bug fix #19286 (httpClient incorrectly closing tunnelled connection right after tunnell
established)
  Bug fix #19226 (NTLM authentication failed due to closing of connection)
  
  Contributed by Michael Becke & Oleg Kalnichevski
  
  Revision  Changes    Path
  1.12      +124 -51   jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/ConnectMethod.java
  
  Index: ConnectMethod.java
  ===================================================================
  RCS file: /home/cvs/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/ConnectMethod.java,v
  retrieving revision 1.11
  retrieving revision 1.12
  diff -u -r1.11 -r1.12
  --- ConnectMethod.java	4 Apr 2003 02:37:02 -0000	1.11
  +++ ConnectMethod.java	25 Apr 2003 18:03:28 -0000	1.12
  @@ -65,16 +65,16 @@
   
   import java.io.IOException;
   
  -import org.apache.commons.httpclient.auth.HttpAuthenticator;
   import org.apache.commons.logging.Log;
   import org.apache.commons.logging.LogFactory;
   
   /**
    * <p>Wraps another method to tunnel through a proxy.</p>
    *
  - * @author Ortwin Gl�ck
  + * @author Ortwin Glueck
    * @author dIon Gillard
    * @author <a href="mailto:mbowler@GargoyleSoftware.com">Mike Bowler</a>
  + * @author <a href="mailto:oleg@ural.ru">Oleg Kalnichevski</a>
    * @since 2.0
    * @version $Revision$ $Date$
    */
  @@ -102,6 +102,92 @@
           return NAME;
       }
   
  +
  +    /**
  +     * This method does nothing. <tt>CONNECT</tt> request is not supposed 
  +     * to contain <tt>Authorization</tt> request header.
  +     *
  +     * @param state current state of http requests
  +     * @param conn the connection to use for I/O
  +     *
  +     * @throws IOException when errors occur reading or writing to/from the
  +     *         connection
  +     * @throws HttpException when a recoverable error occurs
  +     *  
  +     * @see HttpMethodBase#addAuthorizationRequestHeader(HttpState, HttpConnection)
  +     */
  +    protected void addAuthorizationRequestHeader(HttpState state, HttpConnection conn)
  +        throws IOException, HttpException
  +    {
  +        // Do nothing. Not applicable to CONNECT method
  +    }
  +
  +    /**
  +     * This method does nothing. <tt>CONNECT</tt> request is not supposed 
  +     * to contain <tt>Content-Length</tt> request header.
  +     *
  +     * @param state current state of http requests
  +     * @param conn the connection to use for I/O
  +     *
  +     * @throws IOException when errors occur reading or writing to/from the
  +     *         connection
  +     * @throws HttpException when a recoverable error occurs
  +     *  
  +     * @see HttpMethodBase#addContentLengthRequestHeader(HttpState, HttpConnection)
  +     */
  +    protected void addContentLengthRequestHeader(HttpState state, HttpConnection conn)
  +        throws IOException, HttpException
  +    {
  +        // Do nothing. Not applicable to CONNECT method
  +    }
  +
  +    /**
  +     * This method does nothing. <tt>CONNECT</tt> request is not supposed 
  +     * to contain <tt>Cookie</tt> request header.
  +     *
  +     * @param state current state of http requests
  +     * @param conn the connection to use for I/O
  +     *
  +     * @throws IOException when errors occur reading or writing to/from the
  +     *         connection
  +     * @throws HttpException when a recoverable error occurs
  +     *  
  +     * @see HttpMethodBase#addCookieRequestHeader(HttpState, HttpConnection)
  +     */
  +    protected void addCookieRequestHeader(HttpState state, HttpConnection conn)
  +        throws IOException, HttpException
  +    {
  +        // Do nothing. Not applicable to CONNECT method
  +    }
  +
  +
  +    /**
  +     * Populates the request headers map to with additional {@link Header
  +     * headers} to be submitted to the given {@link HttpConnection}.
  +     *
  +     * <p>
  +     * This implementation adds <tt>User-Agent</tt>, <tt>Host</tt>,
  +     * and <tt>Proxy-Authorization</tt> headers, when appropriate.
  +     * </p>
  +     *
  +     * @param state the client state
  +     * @param conn the {@link HttpConnection} the headers will eventually be
  +     *        written to
  +     * @throws IOException when an error occurs writing the request
  +     * @throws HttpException when a HTTP protocol error occurs
  +     *
  +     * @see #writeRequestHeaders
  +     */
  +    protected void addRequestHeaders(HttpState state, HttpConnection conn)
  +        throws IOException, HttpException
  +    {
  +        LOG.trace("enter ConnectMethod.addRequestHeaders(HttpState, "
  +            + "HttpConnection)");
  +        addUserAgentRequestHeader(state, conn);
  +        addHostRequestHeader(state, conn);
  +        addProxyAuthorizationRequestHeader(state, conn);
  +    }
  +
       /**
        * Execute this method by tunnelling and then executing the wrapped method.
        *
  @@ -120,42 +206,29 @@
           if ((code >= 200) && (code < 300)) {
               conn.tunnelCreated();
               code = method.execute(state, conn);
  -        }
  -        return code;
  -    }
  -
  -    /**
  -     * Writes a minimal set of headers to the proxy.
  -     *
  -     * @param state the current http state
  -     * @param conn the connection to write to
  -     * @throws HttpException when an error occurs writing the headers
  -     * @throws IOException when an error occurs writing the headers
  -     */
  -    protected void writeRequestHeaders(HttpState state, HttpConnection conn) 
  -    throws HttpException, IOException {
  -        LOG.trace("enter ConnectMethod.writeRequestHeaders(HttpState, "
  -            + "HttpConnection)");
  -
  -        if (method instanceof HttpMethodBase) {
  -            ((HttpMethodBase) method).addRequestHeaders(state, conn);
  -        }
  -        String line = method.getRequestHeader("Host").toExternalForm();
  -        conn.print(line);
  -        if (Wire.enabled()) {
  -            Wire.output(line);
  -        }
  -        Header header = method.getRequestHeader(HttpAuthenticator.PROXY_AUTH_RESP);
  -        if (header == null) {
  -            header = getRequestHeader(HttpAuthenticator.PROXY_AUTH_RESP);
  -        }
  -        if (header != null) {
  -            line = header.toExternalForm();
  -            conn.print(line);
  -            if (Wire.enabled()) {
  -                Wire.output(line);
  +        } else {
  +            // What is to follow is an ugly hack.
  +            // I REALLY hate having to resort to such
  +            // an appalling trick
  +            // TODO: Connect method must be redesigned.
  +            // The only feasible solution is to split monolithic
  +            // HttpMethod into HttpRequest/HttpResponse pair.
  +            // That would allow to execute CONNECT method 
  +            // behind the scene and return CONNECT HttpResponse 
  +            // object in response to the original request that 
  +            // contains the correct status line, headers & 
  +            // response body.
  +            
  +            LOG.debug("Release connection and fake the response for the original method");
  +            releaseConnection();
  +            if (method instanceof HttpMethodBase ) {
  +                // This sucks
  +                ((HttpMethodBase)method).fakeResponse(
  +                  this.getStatusLine(), 
  +                  this.getResponseHeaderGroup());
               }
           }
  +        return code;
       }
   
       /**
  @@ -170,22 +243,22 @@
       throws IOException, HttpException {
           int port = conn.getPort();
           if (port == -1) {
  -            port = conn.isSecure() ? 443 : 80;
  +            port = conn.getProtocol().getDefaultPort();  
  +        }
  +        StringBuffer buffer = new StringBuffer();
  +        buffer.append(getName()); 
  +        buffer.append(' '); 
  +        buffer.append(conn.getHost()); 
  +        if (port > -1) {
  +            buffer.append(':'); 
  +            buffer.append(port); 
           }
  -        String line = getName() + " " + conn.getHost() + ":" + port 
  -            + " HTTP/1.1";
  +        buffer.append(" HTTP/1.1"); 
  +        String line = buffer.toString();
           conn.printLine(line);
           if (Wire.enabled()) {
               Wire.output(line);
           }
  -    }
  -
  -    /**
  -     * Does nothing.  This should be handled by the actual method.
  -     * 
  -     * @see HttpMethodBase#responseBodyConsumed()
  -     */
  -    protected void responseBodyConsumed() {
       }
   
       /**
  
  
  
  1.59      +5 -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.58
  retrieving revision 1.59
  diff -u -r1.58 -r1.59
  --- HttpConnection.java	22 Apr 2003 18:11:01 -0000	1.58
  +++ HttpConnection.java	25 Apr 2003 18:03:28 -0000	1.59
  @@ -451,7 +451,7 @@
        * @return <tt>true</tt> if I am connected
        */
       public boolean isOpen() {
  -        if (isStale()) {
  +        if (used && isStale()) {
               LOG.debug("Connection is stale, closing...");
               close();
           }
  
  
  
  1.137     +54 -19    jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/HttpMethodBase.java
  
  Index: HttpMethodBase.java
  ===================================================================
  RCS file: /home/cvs/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/HttpMethodBase.java,v
  retrieving revision 1.136
  retrieving revision 1.137
  diff -u -r1.136 -r1.137
  --- HttpMethodBase.java	22 Apr 2003 17:25:40 -0000	1.136
  +++ HttpMethodBase.java	25 Apr 2003 18:03:28 -0000	1.137
  @@ -860,25 +860,48 @@
   
       /**
        * Return true if we should close the connection now.  The connection will
  -     * only be left open if we are using HTTP1.1
  +     * only be left open if we are using HTTP1.1 or if "Connection: keep-alive" 
  +     * was sent.
  +     * 
        * @return boolean true if we should close the connection.
        */
  -    protected boolean shouldCloseConnection() {
  -        if (!http11) {
  -            LOG.debug("Should close connection since using HTTP/1.0.");
  -            return true;
  +    protected boolean shouldCloseConnection(HttpConnection conn) {
  +
  +        Header connectionHeader = null;
  +        if (conn.isTransparent()) {
  +            connectionHeader = getResponseHeader("connection");
           } else {
  -            Header connectionHeader = getResponseHeader("connection");
  -            if (null != connectionHeader
  -                && "close".equalsIgnoreCase(connectionHeader.getValue())) {
  -                LOG.debug("Should close connection since \"Connection: close\" header found.");
  +            connectionHeader = getResponseHeader("proxy-connection");
  +        }
  +        if (connectionHeader != null) {
  +            if (connectionHeader.getValue().equalsIgnoreCase("close")) {
  +                if (LOG.isDebugEnabled()) {
  +                    LOG.debug("Should close connection in response to " + 
  +                      connectionHeader.toExternalForm());
  +                }
                   return true;
  +            } else if (connectionHeader.getValue().equalsIgnoreCase("keep-alive")) {
  +                if (LOG.isDebugEnabled()) {
  +                    LOG.debug("Should NOT close connection in response to " + 
  +                      connectionHeader.toExternalForm());
  +                }
  +                return false;
  +            } else {
  +                if (LOG.isDebugEnabled()) {
  +                    LOG.debug("Unknown directive: " + connectionHeader.toExternalForm());
  +                }
               }
           }
  -        return false;
  +        LOG.debug("Resorting to protocol version default close connection policy");
  +        // missing or invalid connection header, do the default
  +        if (http11) {
  +            LOG.debug("Should NOT close connection, using HTTP/1.1.");
  +        } else {
  +            LOG.debug("Should close connection, using HTTP/1.0.");
  +        }
  +        return !http11;
       }
       
  -    
       /**
        * Return true if a retry is needed.
        * @param statusCode The status code
  @@ -1914,9 +1937,7 @@
           } else {
               int expectedLength = getResponseContentLength();
               if (expectedLength == -1) {
  -                if (canResponseHaveBody(statusLine.getStatusCode()) 
  -                    && !getName().equalsIgnoreCase("connect")
  -                ) {
  +                if (canResponseHaveBody(statusLine.getStatusCode())) {
                       result = is;            
                   }
               } else {
  @@ -2527,7 +2548,7 @@
           responseStream = null;
           responseConnection.setLastResponseInputStream(null);
   
  -        if (shouldCloseConnection()) {
  +        if (shouldCloseConnection(responseConnection)) {
               responseConnection.close();
           }
   
  @@ -2591,6 +2612,20 @@
        */
       public void setMethodRetryHandler(MethodRetryHandler handler) {
           methodRetryHandler = handler;
  +    }
  +
  +    /**
  +     * This method is a dirty hack intended to work around 
  +     * current (2.0) design flaw that prevents the user from
  +     * obraining correct status code and headers from the 
  +     * preceding HTTP CONNECT method.
  +     * 
  +     * TODO: Remove this crap as soon as possible
  +     */
  +
  +    protected void fakeResponse(StatusLine statusline, HeaderGroup responseheaders) {
  +        this.statusLine = statusline;
  +        this.responseHeaders = responseheaders;
       }
   
   }
  
  
  

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


Mime
View raw message