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).
3.138.35.255