O'Reilly logo

RESTful Web Services by Sam Ruby, Leonard Richardson

Stay ahead with the world's most comprehensive technology and business learning platform.

With Safari, you learn the way you learn best. Get unlimited access to videos, live online training, learning paths, books, tutorials, and more.

Start Free Trial

No credit card required

3xx: Redirection

The 3xx status codes indicate that the client needs to do some extra work to get what it wants. They’re most commonly used with GET requests, and they usually tell the client that it can only get the representation it wants by sending a second GET request to some other URI. This secondary URI is sent in the Location response header.

This is the trickiest set of response codes, because 301 (“Moved Permanently”), 302 (“Found”), 303 (“See Other”), and 307 (“Temporary Redirect”) are all very similar. Many applications use these status codes indiscriminately as a way of bouncing the client around from URI to URI, with little regard for what this means in terms of the underlying resources. My main goal in this section is to clear up the confusion.

300 (“Multiple Choices”)

Importance: Low.

The server can send this status code when it has multiple representations of a requested resource, and it doesn’t know which representation the client wants. Either the client didn’t use the Accept-* headers to specify a representation, or it asked for a representation that doesn’t exist.

In this situation, the server can just pick its preferred representation, and send it along with a 200 (“OK”) status code. But it may decide instead to send a 300 along with a list of possible URIs to different representations.

Response headers: If the server has a preferred representation, it can put the URI to that representation in Location. As with other 3xx status codes, the client may automatically follow the URI in Location.

Entity-body: A list of URIs to representations, annotated with any information necessary to let the user make a choice between them. An XHTML list of links is a good format for this.

301 (“Moved Permanently”)

Importance: Medium.

The server knows which resource the client is trying to access, but it doesn’t care for the URI it used to request the resource. It wants the client to take note of the new URI, and use it in future requests.

You can use this status code to keep old URIs from breaking when your URIs change.

Response headers: The server should put the canonical URI in Location.

Entity-body: The server should send a short XHTML file with a hyperlink to the new location, but it’s not necessary.

302 (“Found”)

Importance: Very important to know about, especially when writing clients. I don’t recommend using it.

This status code is the ultimate source of most redirection-related confusion. It’s supposed to be handled just like 307 (“Temporary Redirect”). In fact, in HTTP 1.0 its name was “Moved Temporarily.” Unfortunately, in real life most clients handle 302 just like 303 (“See Other”). The difference hinges on what the client is supposed to do when it gets a 302 in response to a PUT, POST, or DELETE request. See the entry for 307 below if you’re interested in the details.

To resolve this ambiguity, in HTTP 1.1 this response code was renamed to “Found,” and response code 307 was created. This response code is still in wide use, but it’s ambiguous, and I recommend that your services send 303 and 307 instead. The only exception is if you know you’re dealing with an HTTP 1.0 client that doesn’t understand 303 or 307.

Response headers: The Location header contains the URI to which the client should resubmit the request.

Entity-body: Should contain a hypertext document linking to the new URI, as with 301.

303 (“See Other”)

Importance: High.

The request has been processed, but instead of the server sending a response document, it’s sending the client the URI of a response document. This may be the URI to a static status message, or the URI to some more interesting resource. In the latter case, a 303 is a way for the server to send a representation of a resource without forcing the client to download all that data. The client is expected to send a GET request to the value of Location, but it doesn’t have to.

The 303 status code is a good way to canonicalize your resources. You can make them available through many URIs, but only have one “real” URI per representation. All the other URIs use a 303 to point to the canonical URI for that representation. For instance, a 303 might redirect a request for http://www.example.com/software/current.tar.gz to the URI http://www.example.com/software/1.0.2.tar.gz.

Compare to 307 (“Temporary Redirect”).

Response headers: The Location header contains the URI of the representation.

Entity-body: Should contain a hypertext document linking to the new URI, as with 301.

304 (“Not Modified”)

Importance: High.

This status code is similar to 204 (“No Content”) in that the response body must be empty. But 204 is used when there is no body data to send, and 304 is used when there is data but the client already has it. There’s no point in sending it again.

This status code is used in conjunction with conditional HTTP requests. If the client sends an If-Modified-Since header with a date of Sunday, and the representation hasn’t changed since Sunday, then a 304 is appropriate. A 200 (“OK”) would also be appropriate, but sending the representation again would use bandwidth to no purpose. The client already has the representation.

Response headers: The Date header is required. The ETag and Content-Location headers should be set to the same values that would have been sent if the response code were 200 (“OK”).

The caching headers Expires, Cache-Control, and Vary are required if they’ve changed from those sent previously.

There are complicated caching rules about this that I won’t cover here, but the server can send updated headers without sending a new body. This is useful when a representation’s metadata has changed, but the representation itself hasn’t.

Entity-body: Not allowed.

305 (“Use Proxy”)

Importance: Low.

This status code is used to tell the client that it should repeat its request, but go through an HTTP proxy instead of going to the server directly. This code is rarely used because it’s very rare for a server to care that the client use a specific proxy.

This code would be used more frequently if there were proxy-based mirror sites. Today, a mirror site for http://www.example.com/ provides the same content but at a different URI, say http://www.example.com.mysite.com/. The original site might use the 307 (“Temporary Redirect”) status code to send clients to an appropriate mirror site.

If there were proxy-based mirror sites, then you would access the mirror with the same URI as the original (http://www.example.com/), but set http://proxy.mysite.com/ as your proxy. Here, the original example.com might use the 305 status code to route clients to a mirror proxy that’s geographically close to them.

Web browsers typically don’t handle this status code correctly: another reason for its lack of popularity.

Response headers: The Location header contains the URI to the proxy.

306: Unused

Importance: None.

The 306 status code never made it into an HTTP standard. It was described in the Internet Draft “HTTP/1.1 305 and 306 Response Codes” as “Switch Proxy,” a status code sent by a proxy server to get the client to start using a different proxy. Don’t worry about it.

307 (“Temporary Redirect”)

Importance: High.

The request has not been processed, because the requested resource is not home: it’s located at some other URI. The client should resubmit the request to another URI.

For GET requests, where the only thing being requested is that the server send a representation, this status code is identical to 303 (“See Other”). A typical case where 307 is a good response to a GET is when the server wants to send a client to a mirror site. But for POST, PUT, and DELETE requests, where the server is expected to take some action in response to the request, this status code is significantly different from 303.

A 303 in response to a POST, PUT, or DELETE means that the operation has succeeded but that the response entity-body is not being sent along with this request. If the client wants the response entity-body, it needs to make a GET request to another URI.

A 307 in response to a POST, PUT, or DELETE means that the server has not even tried to perform the operation. The client needs to resubmit the entire request to the URI in the Location header.

An analogy may help. You go to a pharmacy with a prescription to be filled. A 303 is the pharmacist saying “We’ve filled your prescription. Go to the next window to pick up your medicine.” A 307 is the pharmacist saying “We can’t fill that prescription. Go to the pharmacy next door.”

Response headers: The Location header contains the URI to which the client should resubmit the request.

Entity-body: Should contain a hypertext document linking to the new URI, as with 301.

With Safari, you learn the way you learn best. Get unlimited access to videos, live online training, learning paths, books, interactive tutorials, and more.

Start Free Trial

No credit card required