You need to retrieve the same content more than once, and you would like to have the server only send the content if it has changed since the last request.
Create a GetMethod and set the
If-None-Match and If-Modified-Since headers; these two headers
will instruct the server to refrain from sending content if the content
has not been altered since the last request. Example 11-1 makes three separate
requests for the same URL (http://www.apache.org), and, because
the content remains static, it is only sent in the response body of the
first request.
Example 11-1. Requesting information with a conditional GET
import java.io.IOException;
import org.apache.commons.httpclient.Header;
import org.apache.commons.httpclient.HeaderElement;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.HttpMethod;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.methods.GetMethod;
public
class ConditionalGetExample {
public
static
void main(String[] args) throws HttpException, IOException {
ConditionalGetExample example = new ConditionalGetExample( );
example.start( );
}
String entityTag = "";
String lastModified = "";
public
void start( ) throws HttpException, IOException {
HttpClient client = new HttpClient( );
HttpMethod method = new GetMethod("http://www.apache.org");
for( int i = 0; i < 3; i++ ) {
setHeaders(method);
client.executeMethod(method);
processResults(method);
method.releaseConnection( );
method.recycle( );
}
}
private
void setHeaders(HttpMethod method) {
method.setRequestHeader(new Header("If-None-Match", entityTag ) );
method.setRequestHeader(new Header("If-Modified-Since",
lastModified ) );
}
private
void processResults(HttpMethod method) throws HttpException {
if(method.getStatusCode( ) == HttpStatus.SC_NOT_MODIFIED ) {
System.out.println( "Content not modified since last request" );
} else {
entityTag = retrieveHeader( method, "ETag" );
lastModified = retrieveHeader( method, "Last-Modified" );
System.out.println( "Get Method retrieved content." );
System.out.println( "Entity Tag: " + entityTag );
System.out.println( "Last Modified: " + lastModified );
}
}
private String retrieveHeader( HttpMethod method, String name )
throws HttpException {
HeaderElement[] header = method.getResponseHeader("ETag").
getElements( );
String value = "";
if(header.length > 0) {
value = header[0].getName( );
}
return value;
}
}Example 11-1 requests the
same page three times; the first request retrieves the content, and the
second and third requests contain the headers for a conditional HTTP
GET. Because the Apache homepage remains unchanged throughout this
example, the content of http://www.apache.org is retrieved
only once. This example uses the headers in the first response to
populate the If-None-Match and
If-Modified-Since headers for the
second and third requests:
Request 1. Get Method retrieved content. Entity Tag: "2da794a-2d0d-998ebc80" Last Modified: Wed, 14 Apr 2004 05:53:38 GMT Request 2. Content not modified since last request Request 3. Content not modified since last request
This first request is similar to a regular HTTP GET, and if you examine the contents of the first request and response, you will see that the server's response contains two headers:
Last-Modified: Wed, 05 May 2004 02:51:59 GMT ETag: "a06d2-76-829811c0"
Example 11-1 takes the
values of these two response headers and stores them in the entityTag and lastModified variables. When the next request
is made, the values of these two variables are used to populate the
conditional headers If-None-Match
and If-Modified-Since in the
setHeaders() method. These request
headers are present in the second request for the same resource:
GET / HTTP/1.1 If-None-Match: "2da7807-31a8-e1eeb400" If-Modified-Since: Tue, 11 May 2004 23:57:04 GMT User-Agent: Jakarta Commons-HttpClient/3.0final Host: www.apache.org
When the server receives these conditional headers, it will check
to see if the resource has been modified. If the resource has been
modified, the resource will have a different modified date and different
entity tag value. If the resource has not been modified, the server will
respond to HttpClient with a 304 Not Modified response code:
HTTP/1.1 304 Not Modified Date: Sat, 15 May 2004 16:59:23 GMT Server: Apache/2.0.49-dev (Unix) ETag: "2da7807-31a8-e1eeb400" Expires: Sun, 16 May 2004 16:59:23 GMT Cache-Control: max-age=86400
The ETag header is known as an entity
tag, and it is similar to a hash code for a resource served
by a particular web server. Different servers have different algorithms
for creating an ETag header; for
example, the Apache HTTPD server has a configuration directive, which
allows you to base an ETag on a
configurable set of file attributes, such as size, i-node number, and
modified time. Consider an ETag to
be a unique identifier for a particular version of a resource; if this
header changes, the corresponding resource has been altered.
Entity tags (the ETag header)
are described in sections 3.11 and 14.19 of RFC 2616 (http://www.zvon.org/tmRFC/RFC2616/Output/index.html).
The Apache HTTPD server can be configured to use different file
attributes when creating an ETag
header. For more information about configuring the Apache HTTPD
server
via
the FileETag directive, see the
documentation of Apache's core features (http://httpd.apache.org/docs-2.0/mod/core.html#fileetag).
