Hi, Attached is a patch (diff.txt) and the full changed files (changes-evert.zip) which includes: - Sachin's changes for SSL tunneling - Changes to enable an alternative SSLSocketFactory to be set, for getting around "untrusted server certificate chain" errors. - Changes to give access to the time when the request was made and the connection established, for monitoring purposes. - Lastly, I've been trying to implement support for authenticated proxies, BUT WITHOUT SUCCESS YET.
With the authenticated proxy, I don't know whether there is something wrong with the proxy I am using or something else. The code is supposed to handle authenticated proxies for both http and https requests. I am getting "no route to host" responses with https and "access to host forbidden on this server" responses with http. I might just no longer have the right permissions on the proxy server. If someone has access to an authenticated proxy and is willing to help test and debug this, I would greatly appreciate it. BTW, it might be a good idea to compare my files to the ones that Sachin sent yesterday, because I had to make changes to his changes in order to support authenticated proxies. Regards, Evert
Index: src/java/org/apache/commons/httpclient/HttpConnection.java =================================================================== RCS file: /home/cvspublic/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/HttpConnection.java,v retrieving revision 1.9 diff -c -r1.9 HttpConnection.java *** src/java/org/apache/commons/httpclient/HttpConnection.java 12 Apr 2002 21:09:20 -0000 1.9 --- src/java/org/apache/commons/httpclient/HttpConnection.java 13 Jun 2002 14:22:10 -0000 *************** *** 66,72 **** --- 66,74 ---- import java.net.SocketException; import java.io.InputStream; import java.io.OutputStream; + import java.io.UnsupportedEncodingException; import java.io.IOException; + import javax.net.SocketFactory; import javax.net.ssl.SSLSocket; import javax.net.ssl.SSLSocketFactory; import org.apache.commons.httpclient.log.*; *************** *** 115,121 **** } /** ! * Fully-specified constructor. * @param proxyHost the host I should proxy via * @param proxyPort the port I should proxy via * @param host the host I should connect to. Parameter value must be non-null. --- 117,123 ---- } /** ! * Constructor. * @param proxyHost the host I should proxy via * @param proxyPort the port I should proxy via * @param host the host I should connect to. Parameter value must be non-null. *************** *** 123,128 **** --- 125,145 ---- * @param secure when <tt>true</tt>, connect via HTTPS (SSL) */ public HttpConnection(String proxyHost, int proxyPort, String host, int port, boolean secure) { + this(proxyHost, proxyPort, host, port, secure, null, null); + } + + /** + * Fully-specified constructor. + * @param proxyHost the host I should proxy via + * @param proxyPort the port I should proxy via + * @param host the host I should connect to. Parameter value must be non-null. + * @param port the port I should connect to + * @param secure when <tt>true</tt>, connect via HTTPS (SSL) + * @param state the HttpSharedState for establishing connections through authenticated proxies. + * @param factory the factory to be used for creating SSL sockets. Or, null for the default. + */ + public HttpConnection(String proxyHost, int proxyPort, String host, int port, boolean secure, + HttpSharedState state, SSLSocketFactory factory) { log.debug("HttpConnection.HttpConnection"); if (host == null) { throw new NullPointerException("host parameter is null"); *************** *** 132,137 **** --- 149,156 ---- _host = host; _port = port; _ssl = secure; + _state = state; + _sslSocketFactory = factory; } // ------------------------------------------ Attribute Setters and Getters *************** *** 278,289 **** assertNotOpen(); // ??? is this worth doing? try { if (null == _socket) { - String host = (null == _proxyHost) ? _host : _proxyHost; - int port = (null == _proxyHost) ? _port : _proxyPort; if (_ssl) { ! _socket = SSLSocketFactory.getDefault().createSocket(host,port); } else { _socket = new Socket(host,port); } } _socket.setSoTimeout(_so_timeout); --- 297,322 ---- assertNotOpen(); // ??? is this worth doing? try { if (null == _socket) { if (_ssl) { ! if (_sslSocketFactory == null) ! _sslSocketFactory = (SSLSocketFactory)SSLSocketFactory.getDefault(); ! if ((_proxyHost != null) && (_proxyPort > 0)) { ! // ssl using proxy - create a tunnellec connection ! doTunnelHandshake(false, null); ! Socket tunnel = _socket; ! _socket = _sslSocketFactory.createSocket(tunnel, _host, _port, true); ! } else { ! // using with no proxy ! _socket = _sslSocketFactory.createSocket(_host, _port); ! } } else { + // non ssl connection + String host = (null == _proxyHost) ? _host : _proxyHost; + int port = (null == _proxyHost) ? _port : _proxyPort; _socket = new Socket(host,port); + // Not creating a tunnel socket, but authenticating. + if ((_proxyHost != null) && (_proxyPort > 0)) + doTunnelHandshake(false, null); } } _socket.setSoTimeout(_so_timeout); *************** *** 298,303 **** --- 331,428 ---- } } + private void doTunnelHandshake(boolean authenticate, String realm) throws IOException + { + String authorizationHeader = null; + if (authenticate && _state != null) { + Credentials credentials = _state.getCredentials(realm); + if ((credentials != null) && + (credentials instanceof UsernamePasswordCredentials)) { + try { + authorizationHeader = Authenticator.basic((UsernamePasswordCredentials)credentials); + } catch (HttpException ex) { + log.debug("doTunnelHandshake(): Exception reading credentials: " + ex); + } + } + else if (realm != null) { + // Try it once with the default credentials that are stored + // with a null realm. + doTunnelHandshake(true, null); + return; + } + } + Socket tunnel = new Socket(_proxyHost, _proxyPort); + OutputStream out = tunnel.getOutputStream(); + String msg = "CONNECT " + _host + ":" + _port + " HTTP/1.0\r\n" + + "User-Agent: " + sun.net.www.protocol.http.HttpURLConnection.userAgent + "\r\n" + + "Host: " + _host + ":" + _port + "\r\n" + + "Content-Length: 0\r\n" + + "Proxy-Connection: Keep-Alive\r\n" + + "Pragma: no-cache\r\n"; + if (authorizationHeader != null) + msg += "Proxy-Authorization: " + authorizationHeader + "\r\n"; + msg += "\r\n"; + + wireLog.info(">>\r\n" + msg); + + byte b[]; + try { + b = msg.getBytes("ASCII7"); + } catch (UnsupportedEncodingException ignored) { + b = msg.getBytes(); + } + out.write(b); + out.flush(); + + _input = tunnel.getInputStream(); + boolean error = false; + + _open = true; + StringBuffer replyBuffer = new StringBuffer(); + String proxyAuthenticate = null; + while (true) { + String line = readLine(); + if (line == null || line.length() < 0) + break; + replyBuffer.append(line + "\r\n"); + int colonPosition = line.indexOf(":"); + if (colonPosition > -1) { + String key = line.substring(0, colonPosition); + String value = line.substring(colonPosition); + if (key.trim().equalsIgnoreCase("Proxy-Authenticate")) + proxyAuthenticate = value; + } + } + String replyStr = replyBuffer.toString(); + _open = false; + + realm = null; + if (proxyAuthenticate != null) { + int start = proxyAuthenticate.indexOf("\"") + 1; + int end = proxyAuthenticate.lastIndexOf("\""); + if (start > -1 && end > -1 && start != end) + realm = proxyAuthenticate.substring(start, end); + } + if (realm != null) + log.debug("doTunnelHandshake(): Authentication required for realm '" + realm + "'"); + + if (realm != null) { + doTunnelHandshake(true, realm); + return; + } + + log.debug("doTunnelHandshake(): Reply: " + replyStr); + + /* We asked for HTTP/1.0, so we should get that back */ + if (!replyStr.startsWith("HTTP/1.0 200")) { + throw new IOException("Unable to tunnel through " + + _proxyHost + ":" + _proxyPort + + ". Proxy returns \"" + replyStr + "\""); + } + + /* tunneling Handshake was successful! */ + } + /** * Return a {@link RequestOutputStream} * suitable for writing (possibly chunked) *************** *** 593,597 **** private static final byte[] CRLF = "\r\n".getBytes(); /** SO_TIMEOUT value */ private int _so_timeout = 0; ! } --- 718,725 ---- private static final byte[] CRLF = "\r\n".getBytes(); /** SO_TIMEOUT value */ private int _so_timeout = 0; ! /** The factory to be used for creating SSL sockets. **/ ! private SSLSocketFactory _sslSocketFactory = null; ! /** The state to be used for establishing connections through authenticated proxies. **/ ! private HttpSharedState _state = null; } Index: src/java/org/apache/commons/httpclient/HttpConnectionManager.java =================================================================== RCS file: /home/cvspublic/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/HttpConnectionManager.java,v retrieving revision 1.5 diff -c -r1.5 HttpConnectionManager.java *** src/java/org/apache/commons/httpclient/HttpConnectionManager.java 15 Apr 2002 18:35:29 -0000 1.5 --- src/java/org/apache/commons/httpclient/HttpConnectionManager.java 13 Jun 2002 14:22:15 -0000 *************** *** 67,72 **** --- 67,73 ---- import java.util.HashMap; import java.util.List; import java.util.LinkedList; + import javax.net.ssl.SSLSocketFactory; import org.apache.commons.httpclient.log.*; *************** *** 87,92 **** --- 88,95 ---- private int maxConnections = 2; // Per RFC 2616 sec 8.1.4 private String proxyHost = null; private int proxyPort = -1; + private HttpSharedState state = null; + private SSLSocketFactory factory = null; /** * No-args constructor *************** *** 96,101 **** --- 99,113 ---- } /** + * This constructor is necessary for making connections through authenticated proxies. + * @param state for making connections through authenticated proxies, or null. + */ + public HttpConnectionManager(HttpSharedState state) + { + this.state = state; + } + + /** * Set the proxy host to use for all connections. * * @param proxyHost - the proxy host name *************** *** 157,162 **** --- 169,183 ---- } /** + * Allows you to specify a new factory to be used as the default + * for creating SSL sockets. Setting the factory to null will + * reset it to using SSLSocketFactory.getDefault(). + */ + public void setSSLSocketFactory(SSLSocketFactory factory) { + this.factory = factory; + } + + /** * Get an HttpConnection for a given URL. The URL must be fully * specified (i.e. contain a protocol and a host (and optional port number). * If the maximum number of connections for the host has been reached, this *************** *** 249,255 **** if(log.isDebugEnabled()){ log.debug("HttpConnectionManager.getConnection: creating connection for " + host + ":" + port + " via " + proxyHost + ":" + proxyPort); } ! conn = new HttpConnection(proxyHost, proxyPort, host, port, isSecure); numConnections = new Integer(numConnections.intValue()+1); mapNumConnections.put(key, numConnections); }else{ --- 270,276 ---- if(log.isDebugEnabled()){ log.debug("HttpConnectionManager.getConnection: creating connection for " + host + ":" + port + " via " + proxyHost + ":" + proxyPort); } ! conn = new HttpConnection(proxyHost, proxyPort, host, port, isSecure, state, factory); numConnections = new Integer(numConnections.intValue()+1); mapNumConnections.put(key, numConnections); }else{ Index: src/java/org/apache/commons/httpclient/HttpMethod.java =================================================================== RCS file: /home/cvspublic/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/HttpMethod.java,v retrieving revision 1.12 diff -c -r1.12 HttpMethod.java *** src/java/org/apache/commons/httpclient/HttpMethod.java 22 Feb 2002 19:15:54 -0000 1.12 --- src/java/org/apache/commons/httpclient/HttpMethod.java 13 Jun 2002 14:22:16 -0000 *************** *** 262,267 **** --- 262,290 ---- public InputStream getResponseBodyAsStream() throws IOException; /** + * Returns the time in milliseconds when a connection was + * available and open. + * If an error occurred before this event, then it will return <tt>-1</tt>. + */ + public long getWhenConnectedMillis(); + + /** + * Returns the time in milliseconds when the headers of the request + * were sent, not the body of the request. It might first wait for + * a 100 response before sending the body of the request. + * If an error occurred before this event, then it will return <tt>-1</tt>. + */ + public long getWhenRequestedMillis(); + + /** + * Returns the time in milliseconds when the first response was received + * from the server, regardless of whether it was a success, failure + * or continue response. + * If an error occurred before this event, then it will return <tt>-1</tt>. + */ + public long getWhenRespondedMillis(); + + /** * Return <tt>true</tt> if I have been {@link #execute executed} * but not recycled. */ Index: src/java/org/apache/commons/httpclient/HttpMethodBase.java =================================================================== RCS file: /home/cvspublic/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/HttpMethodBase.java,v retrieving revision 1.28 diff -c -r1.28 HttpMethodBase.java *** src/java/org/apache/commons/httpclient/HttpMethodBase.java 16 Apr 2002 14:30:42 -0000 1.28 --- src/java/org/apache/commons/httpclient/HttpMethodBase.java 13 Jun 2002 14:22:23 -0000 *************** *** 405,410 **** --- 405,439 ---- } /** + * Returns the time in milliseconds when a connection was + * available and open. + * If an error occurred before this event, then it will return <tt>-1</tt>. + */ + public long getWhenConnectedMillis() { + return whenConnected; + } + + /** + * Returns the time in milliseconds when the headers of the request + * were sent, not the body of the request. It might first wait for + * a 100 response before sending the body of the request. + * If an error occurred before this event, then it will return <tt>-1</tt>. + */ + public long getWhenRequestedMillis() { + return whenRequested; + } + + /** + * Returns the time in milliseconds when the first response was received + * from the server, regardless of whether it was a success, failure + * or continue response. + * If an error occurred before this event, then it will return <tt>-1</tt>. + */ + public long getWhenRespondedMillis() { + return whenResponded; + } + + /** * Return <tt>true</tt> if I have been {@link #execute executed} * but not recycled. */ *************** *** 466,476 **** --- 495,514 ---- connection.open(); } + if (whenConnected == -1) + whenConnected = System.currentTimeMillis(); + writeRequest(state,connection); used = true; + if (whenRequested == -1) + whenRequested = System.currentTimeMillis(); + // need to close output?, but when? readResponse(state,connection); + + if (whenResponded == -1) + whenResponded = System.currentTimeMillis(); }catch(HttpRecoverableException e){ if(retryCount >= maxRetries){ throw new HttpException(e.toString()); *************** *** 539,657 **** continue; } } - } else if (HttpStatus.SC_MOVED_TEMPORARILY == statusCode || - HttpStatus.SC_MOVED_PERMANENTLY == statusCode || - HttpStatus.SC_TEMPORARY_REDIRECT == statusCode) { - if (getFollowRedirects()) { - // - // Note that we cannot current support - // redirects that change the HttpConnection - // parameters (host, port, protocol) - // because we don't yet have a good way to - // get the new connection. - // - // For the time being, we just return - // the 302 response, and allow the user - // agent to resubmit if desired. - // - Header location = getResponseHeader("location"); - if (location != null) { - URL url = null; - try { - if (location.getValue().startsWith("/")) { - if (log.isDebugEnabled()) { - log.debug("Following relative Location header \"" + location + "\"."); - } - String protocol = connection.isSecure() ? "https" : "http"; - int port = connection.getPort(); - if (-1 == port) { - port = connection.isSecure() ? 443 : 80; - } - url = new URL(protocol,connection.getHost(),port,location.getValue()); - } else if(!isStrictMode() && location.getValue().indexOf("://") < 0) { - /* - * Location doesn't start with / but it doesn't contain a protocol. - * Per RFC 2616, that's an error. In non-strict mode we'll try - * to build a URL relative to the current path. - */ - String protocol = connection.isSecure() ? "https" : "http"; - int port = connection.getPort(); - if(-1 == port) { - port = connection.isSecure() ? 443 : 80; - } - URL currentUrl = new URL(protocol,connection.getHost(),port,getPath()); - url = new URL(currentUrl, location.getValue()); - } else { - url = new URL(location.getValue()); - } - } catch(MalformedURLException e) { - log.error("Exception while parsing location header \"" + location + "\"",e); - throw new HttpException(e.toString()); - } - if ("http".equalsIgnoreCase(url.getProtocol())) { - if (connection.isSecure()) { - log.info("Server is attempting to redirect an HTTPS request to an HTTP one."); - throw new HttpException("Server is attempting to redirect an HTTPS request to an HTTP one."); - } - } else if ("https".equalsIgnoreCase(url.getProtocol())) { - if (!connection.isSecure()) { - log.info("Server is attempting to convert an HTTP request to an HTTP one, which is currently not supported. Returning " + statusCode + "."); - break; - } - } - if (!connection.getHost().equalsIgnoreCase(url.getHost())) { - log.info("Server is attempting to redirect a different host, which is currently not supported. Returning " + statusCode + "."); - break; - } - if (url.getPort() == -1) { - if (connection.isSecure()) { - if (connection.getPort() != 443) { - log.info("Server is attempting to redirect a different port, which is currently not supported. Returning " + statusCode + "."); - break; - } - } else { - if (connection.getPort() != 80) { - log.info("Server is attempting to redirect a different port, which is currently not supported. Returning " + statusCode + "."); - break; - } - } - } else if (connection.getPort() != url.getPort()) { - log.info("Server is attempting to redirect a different port, which is currently not supported. Returning " + statusCode + "."); - break; - } - String absolutePath = URIUtil.getPath(url.toString()); - String qs = URIUtil.getQueryString(url.toString()); - - // if we haven't already, let's try it again with the new path - if (visited.contains(connection.getHost() + ":" + connection.getPort() + "|" + HttpMethodBase.generateRequestLine(connection, getName(),absolutePath,qs,(http11 ? "HTTP/1.1" : "HTTP/1.0")))) { - throw new HttpException("Redirect going into a loop, visited \"" + absolutePath + "\" already."); - } else { - if (log.isDebugEnabled()) { - log.debug("Changing path from \"" + getPath() + "\" to \"" + absolutePath + "\" in response to " + statusCode + " response."); - log.debug("Changing query string from \"" + getQueryString() + "\" to \"" + qs + "\" in response to " + statusCode + " response."); - } - setPath(URIUtil.decode(absolutePath)); - setQueryString(qs); - continue; - } - } else { - // got a redirect response, but no location header - if (log.isInfoEnabled()) { - log.info("HttpMethodBase.execute(): Received " + statusCode + " response, but no \"Location\" header. Returning " + statusCode + "."); - } - break; - } - } else { - // got a redirect response, - // but followRedirects is false - log.info("HttpMethodBase.execute(): Received " + statusCode + " response, but followRedirects is false. Returning " + statusCode + "."); - break; - } - } else { - // neither an UNAUTHORIZED nor a redirect response - // so exit - break; } } return statusCode; --- 577,587 ---- continue; } } } + // Moved the handling of redirects to HttpMultiClient. Replaced all the + // code to build a URL relative to the original URL with: + // URL newUrl = new URL( URL context, String newUrlStr ) --Evert + break; } return statusCode; *************** *** 789,795 **** protected void addHostRequestHeader(HttpState state, HttpConnection conn) throws IOException, HttpException { // add host (should do this conditionally?, i.e., don't send to http/1.0?) if (!requestHeaders.containsKey("host")) { ! setRequestHeader("Host",conn.getHost()); } } --- 719,725 ---- protected void addHostRequestHeader(HttpState state, HttpConnection conn) throws IOException, HttpException { // add host (should do this conditionally?, i.e., don't send to http/1.0?) if (!requestHeaders.containsKey("host")) { ! setRequestHeader("Host", conn.getHost() + ":" + conn.getPort()); } } *************** *** 1239,1244 **** --- 1169,1177 ---- http11 = true; bodySent = false; responseBody = null; + whenConnected = -1; + whenRequested = -1; + whenResponded = -1; } // ---------------------------------------------- Protected Utility Methods *************** *** 1299,1312 **** return (name + " " + buf.toString() + " " + protocol + "\r\n"); } else { if (connection.isSecure()) { ! return (name + ! " https://" + ! connection.getHost() + ! ((443 == connection.getPort() || -1 == connection.getPort()) ? "" : (":" + connection.getPort()) ) + ! buf.toString() + ! " " + ! protocol + ! "\r\n"); } else { return (name + " http://" + --- 1232,1246 ---- return (name + " " + buf.toString() + " " + protocol + "\r\n"); } else { if (connection.isSecure()) { ! // return (name + ! // " https://" + ! // connection.getHost() + ! // ((443 == connection.getPort() || -1 == connection.getPort()) ? "" : (":" + connection.getPort()) ) + ! // buf.toString() + ! // " " + ! // protocol + ! // "\r\n"); ! return (name + " " + buf.toString() + " " + protocol + "\r\n"); } else { return (name + " http://" + *************** *** 1367,1372 **** --- 1301,1312 ---- private int maxRetries = 3; /** True if we're in strict mode. */ private boolean strictMode = true; + /** The moment when an open connection is available. **/ + private long whenConnected = -1; + /** The moment when the request headers have been sent, not the request body. **/ + private long whenRequested = -1; + /** The moment of the first response received back from the server. **/ + private long whenResponded = -1; // -------------------------------------------------------------- Constants Index: src/java/org/apache/commons/httpclient/HttpMultiClient.java =================================================================== RCS file: /home/cvspublic/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/HttpMultiClient.java,v retrieving revision 1.4 diff -c -r1.4 HttpMultiClient.java *** src/java/org/apache/commons/httpclient/HttpMultiClient.java 9 May 2002 19:30:22 -0000 1.4 --- src/java/org/apache/commons/httpclient/HttpMultiClient.java 13 Jun 2002 14:22:24 -0000 *************** *** 63,70 **** --- 63,74 ---- package org.apache.commons.httpclient; import java.io.IOException; + import java.net.MalformedURLException; + import java.net.URL; + import javax.net.ssl.SSLSocketFactory; import org.apache.commons.httpclient.log.*; + import org.apache.commons.httpclient.methods.PostMethod; /** * *************** *** 85,91 **** // ----------------------------------------------------- Instance Variables private HttpSharedState state = null; ! private HttpConnectionManager mgr = new HttpConnectionManager(); private boolean strictMode = true; private int timeoutConnection = 0; private int timeoutRequest = 0; --- 89,95 ---- // ----------------------------------------------------- Instance Variables private HttpSharedState state = null; ! private HttpConnectionManager mgr = null; private boolean strictMode = true; private int timeoutConnection = 0; private int timeoutRequest = 0; *************** *** 100,105 **** --- 104,110 ---- */ public HttpMultiClient() { + mgr = new HttpConnectionManager(getState()); } /** *************** *** 255,260 **** --- 260,285 ---- } /** + * Set the maximum number of connections allowed for a given host:port. + * Per RFC 2616 section 8.1.4, this value defaults to 2. + * + * @param maxConnections - number of connections allowed for each host:port + */ + public void setMaxConnectionsPerHost(int maxConnections) + { + mgr.setMaxConnectionsPerHost(maxConnections); + } + + /** + * Allows you to specify a new factory to be used as the default + * for creating SSL sockets. Setting the factory to null will + * reset it to using SSLSocketFactory.getDefault(). + */ + public void setSSLSocketFactory(SSLSocketFactory factory) { + mgr.setSSLSocketFactory(factory); + } + + /** * * Execute the given {@link HttpUrlMethod} using my current * {@link HttpConnection connection} and {@link HttpState}. *************** *** 268,279 **** --- 293,313 ---- */ public int executeMethod(HttpUrlMethod method) throws IOException, HttpException { + return executeMethod(method, 0); + } + protected int executeMethod(HttpUrlMethod method, int numberOfRedirects) + throws IOException, HttpException + { if (null == method) { throw new NullPointerException("method parameter"); } + if(numberOfRedirects > 10) + { + throw new HttpException("Redirected more than 10 times."); + } HttpConnection connection = mgr.getConnection(method.getUrl(), timeoutConnection); connection.setSoTimeout(timeoutRequest); *************** *** 298,305 **** mgr.releaseConnection(connection); } ! if (status == 301 || status == 302 || ! status == 303 || status == 307) { Header header = method.getResponseHeader("Location"); String url = header.getValue(); --- 332,340 ---- mgr.releaseConnection(connection); } ! if (method.getFollowRedirects() && ! (status == 301 || status == 302 || ! status == 303 || status == 307)) { Header header = method.getResponseHeader("Location"); String url = header.getValue(); *************** *** 308,320 **** log.error("HttpMultiClient.executeMethod: Received redirect without Location header."); throw new HttpException("Received redirect without Location header."); } ! method.recycle(); ! method.setUrl(url); ! return executeMethod(method); } return status; } - } --- 343,376 ---- log.error("HttpMultiClient.executeMethod: Received redirect without Location header."); throw new HttpException("Received redirect without Location header."); } ! ! log.debug("HttpMultiClient.executeMethod: Following redirect to: " + url); ! ! String oldUrlStr = method.getUrl(); ! String oldRequestBody = null; ! if (method instanceof PostMethod) ! { ! oldRequestBody = ((PostMethod)method).getRequestBody(); ! } ! URL oldUrl = null; ! try ! { ! oldUrl = new URL(oldUrlStr); ! } catch (MalformedURLException e) ! { ! // This means the original url was also malformed. But, if that ! // was the case we should never have gotten this far. ! log.debug("HttpMultiClient.executemethod: The original url was malformed: " + e); ! throw e; ! } ! URL newUrl = new java.net.URL(oldUrl, url); method.recycle(); ! method.setUrl(newUrl.toString()); ! if (method instanceof PostMethod) ! ((PostMethod)method).setRequestBody(oldRequestBody); ! return executeMethod(method, numberOfRedirects++); } return status; } } Index: src/java/org/apache/commons/httpclient/methods/PostMethod.java =================================================================== RCS file: /home/cvspublic/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/methods/PostMethod.java,v retrieving revision 1.9 diff -c -r1.9 PostMethod.java *** src/java/org/apache/commons/httpclient/methods/PostMethod.java 24 Apr 2002 14:44:50 -0000 1.9 --- src/java/org/apache/commons/httpclient/methods/PostMethod.java 13 Jun 2002 14:22:26 -0000 *************** *** 236,241 **** --- 236,248 ---- } } + /** + * Returns the post data. + */ + public String getRequestBody() { + return requestBody; + } + /** * @throws IllegalStateException if request params have been added */
changes_evert.zip
Description: Zip archive
-- To unsubscribe, e-mail: <mailto:[EMAIL PROTECTED]> For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>