These status codes indicate that something is wrong on the client side. There’s a problem with authentication, with the format of the representation, or with the HTTP library itself. The client needs to fix something on its end.
This is the generic client-side error status, used when no other 4xx error code is appropriate. It’s commonly used when the client submits a representation along with a PUT or POST request, and the representation is in the right format, but it doesn’t make any sense.
Entity-body: May contain a document describing why the server thinks there’s a client-side error.
The client tried to operate on a protected resource without providing the proper authentication credentials. It may have provided the wrong credentials, or none at all. The credentials may be a username and password, an API key, or an authentication token—whatever the service in question is expecting. It’s common for a client to make a request for a URI and accept a 401 just so it knows what kind of credentials to send and in what format. In fact, the HTTP Digest mode of authentication depends on this behavior.
If the server doesn’t want to acknowledge the existence of the resource to unauthorized users, it may lie and send a 404 (“Not Found”) instead of a 401. The downside of this is that clients need to know, in advance, what kind of authentication the server expects for that resource: things like HTTP Digest won’t work.
Response headers: The
WWW-Authenticate header describes what kind
of authentication the server will accept.
Entity-body: A document describing the failure: why the credentials (if any were provided) were rejected, and what credentials would be accepted. If the end user can get credentials by signing up on a web site, or creating a “user account” resource, a link to the sign up URI is useful.
Apart from its name, this status code is not defined in the HTTP standard: it’s “reserved for future use.” This is because there’s no micropayment system for HTTP. That said, if there ever is a micropayment system for HTTP, web services are among the first places that system will start showing up. If you want to charge your users by the web service request, and your relationship with them makes that possible, you might have a use for this status code. But note that Amazon S3 doesn’t use this status code, and it charges by the request just fine.
The client’s request is formed correctly, but the server doesn’t want to carry it out. This is not merely a case of insufficient credentials: that would be 401 (“Unauthorized”). This is more like a resource that is only accessible at certain times, or from certain IP addresses.
A response of 403 implies that the client requested a resource that really exists. As with 401 (“Unauthorized”), if the server doesn’t want to give out even this information, it can lie and send a 404 (“Not Found”) instead.
If the client’s request is well-formed, why is this status code in the 4xx series (client-side error) instead of the 5xx series (server-side error)? Because the server made its decision based on some aspect of the request other than its form: say, the time of day the request was made.
Entity-body: Optionally, a document describing why the request was denied.
Probably the most famous HTTP status code. 404 indicates that the server can’t map the client’s URI to a resource. Compare 410 (“Gone”), which is slightly more helpful. A web service may use a 404 response as a signal to the client that the URI is “free”; the client can then create a new resource by sending a PUT request to that URI.
Remember that a 404 may be a lie to cover up a 403 or 401. It might be that the resource exists, but the server doesn’t want to let the client know about it.
The client tried to use an HTTP method that this resource doesn’t support. For instance, a read-only resource may support only GET and HEAD. Another resource may allow GET and POST, but not PUT or DELETE.
Response headers: The
Allow header lists the HTTP methods that
this resource does support. The following is a sample header:
Allow: GET, POST
The server may send this response code when the client places so many
restrictions on what it considers an acceptable representation
(probably using the
request headers) that the server can’t send any representation at all.
The server may instead choose to ignore the client’s pickiness, and
simply send its preferred representation along with a response code of
200 (“OK”). This is usually what happens on the human web.
Entity-body: A list of links to acceptable representations, in a format similar to that described in 300 (“Multiple Choices”).
You’ll only see this status code from an HTTP proxy. It’s just like 401 (“Unauthorized”), except the problem is not that you can’t use the web service without credentials: it’s that you can’t use the proxy without credentials. As with 401, the problem may be that the client provided no credentials, or that the credentials provided are bad or insufficient.
Request headers: To send credentials to the
proxy, the client uses the
Proxy-Authorization header instead of
Authorization header. The
format is identical to that of
Response headers: Instead of the
Authenticate header, the proxy fills the
Proxy-Authenticate header with
information about what kind of authentication it expects. The format
is identical to that of
Note that both the proxy and the web service may require credentials, so the client may clear up a 407 only to be hit with a 401 (“Unauthorized”).
If an HTTP client opens a connection to the server, but never sends a request (or never sends the blank line that signals the end of the request), the server should eventually send a 408 response code and close the connection.
Getting this response code means that you tried to put the server’s resources into an impossible or inconsistent state. Amazon S3 gives this response code when you try to delete a bucket that’s not empty. My bookmarking service gives it when you try to change your username to a name that’s already taken.
Response headers: If the conflict is caused
by the existence of some other resource (such as when you try to
change your username to a name that’s taken), the
Location header should point to the URI of
that resource: that is, the source of the conflict.
Entity-body: Should contain a document that describes the conflicts, so that the client can resolve them if possible.
This response code is like 404 (“Not Found”), but it provides a little more information. It’s used when the server knows that the requested URI used to refer to a resource, but no longer does. The server doesn’t know any new URI for the resource; if it did, it would send a 301 (“Permanent Redirect”).
Like the permanent redirect, a 410 response code has the implication that the client should remove the current URI from its vocabulary, and stop making requests for it. Unlike the permanent redirect, the 410 offers no replacement for the bad URI: It’s just gone. RFC 2616 suggests using a 410 response code “for limited-time, promotional services and for resources belonging to individuals no longer working at the server’s site.”
You might be tempted to send this response code in response to a successful DELETE request, but that’s a little too cute. The client wouldn’t know whether it deleted the resource or whether it was gone before it made their request. The correct response to a successful DELETE request is 200 (“OK”).
Importance: Low to medium.
An HTTP request that includes a representation should set the
Content-Length request header to the length
(in bytes) of the representation. Sometimes this is inconvenient for
the client: for instance, when the representation is being streamed
from some other source. So HTTP doesn’t require a client to send the
Content-Length header with each
request. However, the HTTP server is within its rights to require it
for any given request. The server is allowed to
interrupt any request that starts sending a
representation without having provided a
Content-Length, and demand that the client
resubmit the request with a
Content-Length header. This is the response
code that goes along with the interruption.
If the client lies about the length, or otherwise sends too large a representation, the server may interrupt it and close the connection, but in that case the response code is 413 (“Request Entity Too Large”).
The client specified one or more preconditions in its request headers, effectively telling the server to carry out its request only if certain conditions were met. Those conditions were in fact not met, so instead of carrying out the request the server sends this status code.
A common precondition is
If-Unmodified-Since. The client may PUT a
request to modify a resource, but ask that the changes take effect
only if no one else has modified the resource since the client last
fetched it. Without the precondition, the client might overwrite
someone else’s changes without realizing it, or might cause a 409
Request headers: The client might get this
response code by using any of the
If-None-Match is a bit
special. If the client specifies
If-None-Match when making a GET or HEAD
request, and the precondition fails, then the response code is not 412
but 304 (“Not Modified”). This is the basis of conditional HTTP GET.
If a PUT, POST, or DELETE request uses
If-None-Match, and the precondition fails,
then the response code is 412. The response code is also 412 when a
precondition uses the
If-Unmodified-Since headers, no
matter what the HTTP method is.
Importance: Low to medium.
This is similar to 411 (“Length Required”) in that the server can interrupt the client’s request with this status code, and close the connection without waiting for the request to complete. The 411 status code was for requests that didn’t specify the length of their representation. This status code is for requests that send a representation that’s too large for the server to handle.
A look-before-you-leap request (see Chapter 8) is the best way for a client to avoid being interrupted with this error. If the LBYL request gets a response code of 100 (“Continue”), the client can go ahead and submit the full representation.
Response headers: The problem may be
temporary and on the server side (a lack of resources) rather than on
the client side (the representation is just too damn big). If so, the
server may set the
header to a date or a number of seconds, and the client can retry its
The HTTP standard imposes no official limit on the length of a URI (and, in my opinion, there shouldn’t be any). However, most existing web servers impose an upper limit on the length of a URI, and a web service may do the same. The most common cause is a client putting representation data in the URI, when it should be in the entity-body. Deeply-nested data structures can also cause very long URIs.
If the client sends a document that’s got the right media type but the wrong format (such as an XML document written in the wrong vocabulary), a better response is the more generic 400 (“Bad Request”). That’s what I use throughout my bookmark service. If you really want to treat that case specially, you can send the WebDAV extended response code 422 (“Unprocessable Entity”).
The server sends this status code when the client asks for a series of byte-ranges from a representation, but the representation is actually too small for any of the byte-ranges to apply. In other words, if you ask for byte 100 of a 99-byte representation, you’ll get this status code.
Request headers: This status code will only
be sent when the original request included the
Range header request field. It will not be
sent if the original request included the
If-Range header request field;
Response headers: The server should send a
Content-Range field that tells the
client the actual size of the representation.
Importance: Medium, but (as of time of writing) rarely used.
This response code is the flip side of 100 (“Continue”). If you make a LBYL request to see whether the server will accept your representation, and the server decides it will, you get a response code 100 and you can go ahead. If the server decides it won’t accept your representation, you get a response code 417, and you shouldn’t bother sending your representation.