Thanks for the tips. Our use of the executeMethodRedirecting would as a substitute for just calling client.executeMethod(method) which we've placed in a class called HttpClientManager. As such, the outer-code looks like:
----
HttpMethod get = new GetMethod(connectTo);
get.addRequestHeader("Cache-Control", "no-cache");
get.addRequestHeader("User-Agent", CommonUtils.getHttpServer());
get.addRequestHeader(HTTPHeaderName.CONNECTION.httpStringValue(), "close");
get.setFollowRedirects(true);
HttpClient client = HttpClientManager.getNewClient();
try {
HttpClientManager.executeMethodRedirecting(client, get); if(get.getStatusCode() < 200 || get.getStatusCode() >= 300) {
if(LOG.isWarnEnabled())
LOG.warn("Invalid status code: " + get.getStatusCode());
throw new IOException("no 2xx ok.");
}
// ... do stuff.
} catch (IOException ioe) {
// do stuff.
} finally {
if (get != null)
get.releaseConnection();
}---
As may be visible, the object behind the GetMethod must stay the same in order for the lines below executeMethodRedirecting to correctly work. Another way might be to have executeMethodRedirecting return the last HttpMethod used, but there's no way within the method itself to know what kind of method to recreate on subsequent attempts.
Thanks, Sam
Oleg Kalnichevski wrote:
Sam,
I would not bother reusing the method. The whole method recycling
concept is kind of silly. It results in quite a bit of ugly code for
virtually negligible performance gain. Also, I would always have
HttpMethod#releaseConnection in a finally clause.
As to the release of HttpClient 2.1, I would not expect the first alpha earlier than February next year, with the first beta coming by May.
Oleg
On Wed, 2003-11-05 at 21:18, Sam Berlin wrote:
I suppose that'll have to do. ;)
Do you happen to notice anything obviously wrong with the following workaround code? It is designed just to work with GetRequests, although it theoretically should work with any request that does not contain output data (such as a Post). Any ideas on when 2.1 will likely be released as semi-stable?
---
/**
* Executes the given HttpMethod in the HttpClient, following redirecits
* up to the specific number of times.
* This method is needed because HttpClient does not support redirects
* across protocols, hosts, and/or ports.
*/
public static void executeMethodRedirecting(HttpClient client,
HttpMethod methid,
int redirects)
throws IOException, HttpException {
for(int i = 0; i < redirects; i++) {
if(LOG.isInfoEnabled())
LOG.info("Attempting connection (" + i + ") to " +
methid.getURI().getEscapedURI());
client.executeMethod(methid);
switch(methid.getStatusCode()) {
case HttpStatus.SC_MOVED_TEMPORARILY:
case HttpStatus.SC_MOVED_PERMANENTLY:
case HttpStatus.SC_SEE_OTHER:
case HttpStatus.SC_TEMPORARY_REDIRECT:
if(!methid.getFollowRedirects()) {
if(LOG.isInfoEnabled())
LOG.warn("Redirect requested but not supported");
throw new HttpException("Redirect requested");
}
Header locationHeader = methid.getResponseHeader("location");
if(locationHeader == null) {
if(LOG.isInfoEnabled())
LOG.warn("Redirect requested, no location header");
throw new HttpException("Redirected without a location");
}
String location = locationHeader.getValue();
if(LOG.isInfoEnabled())
LOG.info("Redirected requested to: " + location); URI newLocation = new URI(location.toCharArray());
// Retrieve the RequestHeaders
Header[] requestHeaders = methid.getRequestHeaders();
// Recycle this method so we can use it again.
methid.recycle();
HostConfiguration hc = methid.getHostConfiguration();
hc.setHost(
newLocation.getHost(),
newLocation.getPort(),
newLocation.getScheme()
);
methid.setFollowRedirects(true);
for(int j = 0; j < requestHeaders.length; j++) {
if(!requestHeaders[j].getName().equals("Host"))
methid.addRequestHeader(requestHeaders[j]);
}
// Set up the new values for the method.
methid.setPath(newLocation.getEscapedPath());
methid.setQueryString(newLocation.getEscapedQuery());
methid.removeRequestHeader(HttpAuthenticator.WWW_AUTH_RESP);
// Release the existing connection... we know it is not
// the same host/port/protocol, because if it was,
// it would be handled internally by HttpClient.
methid.releaseConnection();
// Loop around and try the method again.
break;
default:
return;
}
}
throw new HttpException("Maximum redirects encountered, bailing");
}
---
Thanks, Sam
Oleg Kalnichevski wrote:
Sam,
The architecture of HttpClient 2.0 is, let me say, well..., sub-optimal.
The problem being that in HttpClient 2.0 redirects are handled by
HttpMethodBase class, whereas connections are managed by HttpClient
(through a HttpConnectionManager to be exact). As a result
HttpMethodBase class has no means of obtaining a new connection when
cross-sire redirect is requested. For various reasons (mainly due to the
popular pressure from other projects reliant on HttpClient 2.0 API) the
problem could not be solved for the 2.0 release.
The bug is already fixed in CVS HEAD, but the code may still be unstable. 2.1 release will be free from this limitation.
Cheers
Oleg
On Wed, 2003-11-05 at 20:05, Sam Berlin wrote:
Hi All,
I'm curious why HttpClient is unable to redirect from one port to another port. Does the HTTP spec disallow this, or does the internals of HttpClient break if the redirect occurs?
Thanks, Sam
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
.
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
.
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
