5.6 HTTP Headers

Java Servlet Programming, 2nd Edition > 5. Sending HTML Information > 5.6 HTTP Headers

 
< BACKCONTINUE >

5.6 HTTP Headers

A servlet can set HTTP headers to provide extra information about its response. As we said in Chapter 4, a full discussion of all the possible HTTP 1.0 and HTTP 1.1 headers is beyond the scope of this book. Table 5-2 lists the HTTP headers that are most often set by servlets as a part of a response.

Table 5-2, HTTP Response Headers

Header

Usage

Cache-Control

Specifies any special treatment a caching system should give to this document. The most common values are no-cache (to indicate this document should not be cached), no-store (to indicate this document should not be cached or even stored by a proxy server, usually due to its sensitive contents), and max-age=seconds (to indicate how long before the document should be considered stale). This header was introduced in HTTP 1.1.[1]

Pragma

This is the HTTP 1.0 equivalent of Cache-Control, with no-cache as its only possible value. It's wise to use Pragma in conjunction with Cache-Control to support older browsers.

Connection

Used to indicate whether the server is willing to maintain an open (persistent) connection to the client. If so, its value is set to keep-alive. If not, its value is set to close. Most web servers handle this header on behalf of their servlets, automatically setting its value to keep-alive when a servlet sets its Content-Length header or when the server can automatically determine the content length.

Retry-After

Specifies a time when the server can again handle requests, used with the SC_SERVICE_UNAVAILABLE status code. Its value is either an int that represents the number of seconds or a date string that represents an actual time.

Expires

Specifies a time when the document may change or when its information will become invalid. It implies that it is unlikely the document will change before that time.

Location

Specifies a new location of a document, usually used with the status codes SC_CREATED, SC_MOVED_PERMANENTLY, and SC_MOVED_TEMPORARILY. Its value must be an fully qualified URL (including http://).

WWW-Authenticate

Specifies the authorization scheme and the realm of authorization required by the client to access the requested URL. Used with the status code SC_UNAUTHORIZED.

Content-Encoding

Specifies the scheme used to encode the response body. Example values are gzip (or x-gzip) and compress (or x-compress). Multiple encodings should be represented as a comma-separated list in the order in which the encodings were applied to the data.

[1] Netscape Navigator and Microsoft Internet Explorer both have bugs that keep this header from always being obeyed. When you must absolutely guarantee servlet output isn't cached, each request to the servlet should use a slightly different URL, perhaps with a little added extraneous parameter information.

5.6.1 Setting an HTTP Header

The HttpServletResponse class provides a number of methods to assist servlets in setting HTTP response headers. Use setHeader( ) to set the value of a header:

public void HttpServletResponse.setHeader(String name, String value)

This method sets the value of the named header as a String. The name is case insensitive, as it is for all these methods. If the header had already been set, the new value overwrites the previous one. Headers of all types can be set with this method.

If you need to specify a timestamp for a header, you can use setDateHeader( ):

public void HttpServletResponse.setDateHeader(String name, long date)

This method sets the value of the named header to a particular date and time. The method accepts the date value as a long that represents the number of milliseconds since the epoch (midnight, January 1, 1970, GMT). If the header has already been set, the new value overwrites the previous one.

Finally, you can use setIntHeader( ) to specify an integer value for a header:

public void HttpServletResponse.setIntHeader(String name, int value)

This method sets the value of the named header as an int. If the header had already been set, the new value overwrites the previous one.

The containsHeader( ) method provides a way to check if a header already exists:

public boolean HttpServletResponse.containsHeader(String name)

This method returns true if the named header has already been set, false if not.

For the relatively rare cases when a servlet has to send multiple values for the same header, there are additional methods.

public void HttpServletResponse.addHeader(String name, String value) public void HttpServletResponse.addDateHeader(String name, long value) public void HttpServletResponse.addIntHeader(String name, int value)

These methods set the header to the given value, but while the traditional setHeader( ) method would replace any existing value or values, addHeader( ) leaves current settings alone and just sets an additional value.

Finally, the HTML 3.2 specification defines an alternate way to set header values using the <META HTTP-EQUIV> tag inside the HTML page itself:

<META HTTP-EQUIV="name" CONTENT="value">

This tag must be sent as part of the <HEAD> section of the HTML page. This technique does not provide any special benefit to servlets; it was developed for use with static documents, which do not have access to their own headers.

5.6.2 Redirecting a Request

One of the useful things a servlet can do using status codes and headers is redirect a request. This is done by sending instructions for the client to use another URL in the response. Redirection is generally used when a document moves (to send the client to the new location), for load balancing (so one URL can distribute the load to several different machines), or for simple randomization (choosing a destination at random).

Example 5-4 shows a servlet that performs a random redirect, sending a client to a random site selected from its site list. Depending on the site list, a servlet like this could have many uses. As it stands now, it's just a jump-off point to a selection of cool servlet sites. With a site list containing advertising images, it can be used to select the next ad banner.

Example 5-4. Random Redirector
import java.io.*; import java.util.*; import javax.servlet.*; import javax.servlet.http.*; public class SiteSelector extends HttpServlet {   Vector sites = new Vector();   Random random = new Random();   public void init() throws ServletException {     sites.addElement("http://www.oreilly.com/catalog/jservlet2");     sites.addElement("http://www.servlets.com");     sites.addElement("http://java.sun.com/products/servlet");     sites.addElement("http://www.newInstance.com");   }   public void doGet(HttpServletRequest req, HttpServletResponse res)                                throws ServletException, IOException {     res.setContentType("text/html");     PrintWriter out = res.getWriter();     int siteIndex = Math.abs(random.nextInt()) % sites.size();     String site = (String)sites.elementAt(siteIndex);     res.setStatus(res.SC_MOVED_TEMPORARILY);     res.setHeader("Location", site);   } }

The actual redirection happens in two lines:

res.setStatus(res.SC_MOVED_TEMPORARILY); res.setHeader("Location", site);

The first line sets the status code to indicate a redirection is to take place, while the second line gives the new location. To guarantee they will work, you must call these methods before the response is committed. Remember, the HTTP protocol sends status codes and headers before the content body. Also, HTTP dictates the new site must be given as an absolute URL (for example, http://server:port/path/file.html). Anything less than that may confuse the client.

These two lines can be simplified to one using the sendRedirect( ) convenience method:

public void HttpServletResponse.sendRedirect(String location)    throws IOException, IllegalStateException

For our example, the two lines become simply:

res.sendRedirect(site);

This method redirects the response to the specified location, automatically setting the status code and Location header. In addition, to support clients without redirect capabilities or that do not recognize the SC_MOVED_TEMPORARILY status code, the method writes a short response body that contains a hyperlink to the new location. Consequently, do not write your own response body when using this method. The sendRedirect( ) method can, beginning with Servlet API 2.2, accept a relative URL. The HTTP specification dictates that all redirect URLs must be absolute; however, this method will transform a relative URL to an absolute form (automatically prepending the current protocol, server, and port but not the context path, do that yourself if necessary) before sending it to the client. Pretty slick! Make sure to call this method before the response is committed, otherwise it will throw an IllegalStateException. This method performs an implicit reset on the response buffer before generating the redirect page. Headers set before sendRedirect( ) remain set.

5.6.3 Watching Links to Other Sites

Redirection can also be used to learn where clients go when they leave your site. Assume you have several pages containing lists of links to other sites. Instead of linking directly to the external site, you can link to a redirecting servlet that can record each time an external link is selected. The HTML looks like this:

<a href="/goto/http://www.servlets.com">Servlets.com</a>

A servlet can be registered to handle the /goto/* path prefix where it will receive the selected URL as extra path info and redirect the client to that location after making a note in the server log. The GoTo servlet code is shown in Example 5-5.

Example 5-5. Where Do You Think You're Going?
import java.io.*; import java.util.*; import javax.servlet.*; import javax.servlet.http.*; public class GoTo extends HttpServlet {   public void doGet(HttpServletRequest req, HttpServletResponse res)                                throws ServletException, IOException {     // Determine the site where they want to go     String site = req.getPathInfo();     String query = req.getQueryString();     // Handle a bad request     if (site == null) {       res.sendError(res.SC_BAD_REQUEST, "Extra path info required");     }     // Cut off the leading "/" and append the query string     // We're assuming the path info URL is always absolute     String url = site.substring(1) + (query == null ? "" : "?" + query);     // Log the requested URL and redirect     log(url);  // or write to a special file     res.sendRedirect(url);   } }

A servlet similar to this could handle aliasing so that /goto/servlets would automatically redirect to http://www.servlets.com. Selling aliases such as this is the business model for http://go.to and http://i.am.

5.6.4 Client Pull

Client pull is similar to redirection, with one major difference: the browser actually displays the content from the first page and waits some specified amount of time before retrieving and displaying the content from the next page. It's called client pull because the client is responsible for pulling the content from the next page.

Why is this useful? For two reasons. First, the content from the first page can explain to the client that the requested page has moved before the next page is automatically loaded. Second, pages can be retrieved in sequence, making it possible to present a slow-motion page animation.

Client pull information is sent to the client using the Refresh HTTP header. This header's value specifies the number of seconds to display the page before pulling the next one, and it optionally includes a URL string that specifies the URL from which to pull. If no URL is given, the same URL is used. Here's a call to setHeader( ) that tells the client to reload this same servlet after showing its current content for three seconds:

setHeader("Refresh", "3");

And here's a call that tells the client to display Netscape's home page after the three seconds:

setHeader("Refresh", "3; URL=http://home.netscape.com");

Example 5-6 shows a servlet that uses client pull to display the current time, updated every 10 seconds.

Example 5-6. The Current Time, Kept Current
import java.io.*; import java.util.*; import javax.servlet.*; import javax.servlet.http.*; public class ClientPull extends HttpServlet {   public void doGet(HttpServletRequest req, HttpServletResponse res)                                throws ServletException, IOException {     res.setContentType("text/plain");     PrintWriter out = res.getWriter();     res.setHeader("Refresh", "10");     out.println(new Date().toString());   } }

This is an example of a text-based animation we'll look at graphical animations in the next chapter. Note that the Refresh header is nonrepeating. It is not a directive to load the document repeatedly. For this example, however, the Refresh header is specified on each retrieval, creating a continuous display.

The use of client pull to retrieve a second document is shown in Example 5-7. This servlet redirects requests for one host to another host, giving an explanation to the client before the redirection.

Example 5-7. An Explained Host Change
import java.io.*; import java.util.*; import javax.servlet.*; import javax.servlet.http.*; public class ClientPullMove extends HttpServlet {   static final String NEW_HOST = "http://www.oreilly.com";   public void doGet(HttpServletRequest req, HttpServletResponse res)                                throws ServletException, IOException {     res.setContentType("text/html");     PrintWriter out = res.getWriter();     String newLocation = NEW_HOST + req.getRequestURI();     res.setHeader("Refresh", "10; URL=" + newLocation);     out.println("The requested URI has been moved to a different host.<BR>");     out.println("Its new location is " + newLocation + "<BR>");     out.println("Your browser will take you there in 10 seconds.");   } }

This servlet generates the new location from the requested URI, which allows it to redirect any requests made to the old server to the same path on the new server. Using the web.xml deployment descriptor, this servlet could be configured to handle every request, to gradually transition clients to the new location.


Last updated on 3/20/2003
Java Servlet Programming, 2nd Edition, © 2001 O'Reilly

< BACKCONTINUE >


Java servlet programming
Java Servlet Programming (Java Series)
ISBN: 0596000405
EAN: 2147483647
Year: 2000
Pages: 223

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net