Common Java Cookbook

Edition: 0.19

Download PDF or Read on Scribd

Download Examples (ZIP)

11.13. Handling Redirects

11.13.1. Problem

You need to access a server that may send an arbitrary number of redirects.

11.13.2. Solution

Before executing an HttpMethod call, setFollowRedirects(true) on the method; HttpClient will take care of following any redirects a server may return in a response. The following example shows what happens when a method requests a CGI script that returns a 302 (moved temporarily) response code:

               import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.HttpMethod;
import org.apache.commons.httpclient.methods.GetMethod;
HttpClient client = new HttpClient( );
String url = "http://www.discursive.com/cgi-bin/jccook/redirect.cgi";
    
System.out.println( "Executing Method not following redirects: ");        
HttpMethod method = new GetMethod( url );
method.setFollowRedirects( false );
executeMethod(client, method);
System.out.println( "Executing Method following redirects: ");        
method = new GetMethod( url );
method.setFollowRedirects( true );
executeMethod(client, method);
private 
               static 
               void executeMethod(HttpClient client, HttpMethod method)
    throws IOException, HttpException {
    client.executeMethod( method );
    System.out.println( "Response Code: " + method.getStatusCode( ) );
    String response = method.getResponseBodyAsString( );
    System.out.println( response );
    method.releaseConnection( );
    method.recycle( );
}

This example executes two GetMethod instances; the first method is configured not to follow redirects, and the second is configured to follow redirects. The first method is executed, and the server sends a 302 response code. Since this method is not configured to follow redirects, HttpClient does not make another request. When the second method is executed, HttpClient follows the initial redirect to a redirect2.cgi script, which sends another redirect to /jccook/index.html:

Executing Method not following redirects: 
0    INFO  [main] org.apache.commons.httpclient.HttpMethodBase     - Redirect 
requested but followRedirects is disabled
Response Code: 302
Executing Method following redirects: 
Response Code: 200
<html>
 <head>
  <title>JCCook Example</title>
 </head>
 <body>
  <h1>Hello World!</h1>
 </body>
</html>

11.13.3. Discussion

HttpClient can handle any of the following response codes specifying a redirect:

  • Status Code 302: HttpStatus.SC_MOVED_TEMPORARILY

  • Status Code 301: HttpStatus.SC_MOVED_PERMANENTLY

  • Status Code 303: HttpStatus.SC_SEE_OTHER

  • Status Code 307: HttpStatus.SC_TEMPORARY_REDIRECT

When a response code is retrieved, HttpClient sends another GET request for the resource specified in the Location header. The following code is the first request sent by a method configured to follow redirects:

GET /cgi-bin/jccook/redirect.cgi HTTP/1.1
User-Agent: Jakarta Commons-HttpClient/3.0final
Host: www.discursive.com

The redirect.cgi script will then send a 302 Moved response, supplying a Location header that points to redirect2.cgi:

HTTP/1.1 302 Moved
Date: Sat, 15 May 2004 19:30:49 GMT
Server: Apache/2.0.48 (Fedora)
Location: /cgi-bin/jccook/redirect2.cgi
Content-Length: 0
Content-Type: text/plain; charset=UTF-8

HttpClient then sends another GET request for the resource specified in the previous response:

GET /cgi-bin/jccook/redirect2.cgi HTTP/1.1
User-Agent: Jakarta Commons-HttpClient/3.0final
Host: www.discursive.com

The redirect2.cgi is configured to send a redirect for /jccook/index.html, and the response to the previous request does just that:

HTTP/1.1 302 Moved
Date: Sat, 15 May 2004 19:30:49 GMT
Server: Apache/2.0.48 (Fedora)
Location: /jccook/index.html
Content-Length: 0
Content-Type: text/plain; charset=UTF-8

How HttpClient handles redirect responses can be further customized by three configurable parameters on HttpClient. REJECT_RELATIVE_REDIRECT causes HttpClient to throw an exception if a server sends a Location header with a relative URL; for instance, if the redirect.cgi script returns a Location header of ../index.html, the redirection causes an exception if REJECT_RELATIVE_REDIRECT is set to true. If ALLOW_CIRCULAR_REDIRECTS is set to true, HttpClient throws an exception if a series of redirects includes the same resources more than once. MAX_REDIRECTS allows you to specify a maximum number of redirects to follow. The following example sets all three parameters on an instance of HttpClientParams associated with an instance of HttpClient:

HttpClient client = new HttpClient( );
HttpClientParams params = client.getParams( );
params.setBooleanParameter( HttpClientParams.REJECT_RELATIVE_REDIRECT, false );
params.setBooleanParameter( HttpClientParams.ALLOW_CIRCULAR_REDIRECTS, false );
params.setIntParameter( HttpClientParams.MAX_REDIRECTS, 10 );

11.13.4. See Also

For more information on how HttpClient handles redirection, take a look at the source for the HttpMethodDirector. The isRedirectNeeded() and processRedirectResponse() methods handle redirection, and the source for this class can be viewed using ViewCVS (http://cvs.apache.org/viewcvs.cgi/jakarta-commons/httpclient/src/java/). Navigate to the org.apache.commons.httpclient package and click on HttpMethodDirector.


Creative Commons License
Common Java Cookbook by Tim O'Brien is licensed under a Creative Commons Attribution-Noncommercial-No Derivative Works 3.0 United States License.
Permissions beyond the scope of this license may be available at http://www.discursive.com/books/cjcook/reference/jakartackbk-PREFACE-1.html. Copyright 2009. Common Java Cookbook Chunked HTML Output. Some Rights Reserved.