HTTP Status: Client Errors
The last post in my HTTP status code series was just over six months ago. I’m sorry for taking so long to revive the series, but I’m back with a discussion about the 4xx status codes. I hope you enjoy it!
The 4xx series of HTTP status codes is intended for client errors. That is, the server determines that there is an error occurring as a result of bad or missing data in the request from the client. The 404 Not Found
status code is the most recognizable of these, and it’s the server’s way of telling the client that the requested URI is not available on the server. This is not the server’s fault, but, rather, it is the client’s, so the server responds saying, “Sorry, pal! I can’t find what you’re looking for.”
In an earlier post, I mentioned the 100 Continue
status code. I mention it again here because the use of an Expect: 100-continue
request header in a “look-before-you-leap” (LBYL) request can be useful to let you know of potential problems with your request before you receive any of these status code responses from the server.
Let’s use the same request from the 100 Continue
post as an example:
POST /content/videos HTTP/1.1
Host: media.example.org
Content-Type: video/mp4
Content-Length: 105910000
Authorization: Basic bWFkZTp5b3VfbG9vaw==
...
Note that this request does not contain the Expect
header, and it is assumed that the body of this request contains the full binary content of the video being posted.
For the sake of example, let’s assume that the server doesn’t allow POST
requests to the /content/videos
URI. If this is the case, then the server should return a 405 Method Not Allowed
status code in response to this request. This is a condition that we could have checked for with the LBYL request prior to sending the full 105,910,000 bytes of the video, thus saving bandwidth, client resources, and server resources.
HTTP/1.1 405 Method Not Allowed
Date: Wed, 28 Jan 2009 03:04:25 GMT
Allow: GET,HEAD
In addition, to the 405 Method Not Allowed
status, according to RFC 2616, the server must included an Allow
header listing the valid methods for the requested resource. Sending the Allow
header in response to HEAD
requests (and all requests for that matter) can also help inform clients of acceptable methods.
If the server does allow POST
requests at this URI but we fail to send the Authorization
header with the request, then the server should respond with a 401 Unauthorized
status, telling the client to resend the request with proper authorization. The server must include a WWW-Authenticate
header in this response to indicate the expected authorization scheme. If the request, however, does include the Authorization
header, as illustrated in the example, but the authentication fails for whatever reason, then the server should respond with a 403 Forbidden
status and a description with the reason for the failure in the response body.
If the request doesn’t include the Content-Length
header, then you might want the server to respond with a 411 Length Required
status. Requiring the length and comparing it to the length of the actual request body is a good way to determine whether there was any loss of data. However, if the integrity of data is a concern, you might want to require clients to include the Content-MD5
header in the request. Since there is no status code to indicate Content-MD5
as a requirement, simply return a 400 Bad Request
status stating your requirement of the Content-MD5
header in the response body.
The 400 Bad Request
status code literally means that the “request could not be understood by the server due to malformed syntax,” but it is a generic enough response that it can be used for a variety of other client errors not covered by the other 4xx series status codes. For example, I have used 400 Bad Request
as a way to indicate data validation failures in POST
and PUT
requests.
If the full request reaches the server, but the server determines that the 105,910,000 bytes of the video is beyond the acceptable limit—maybe we want to limit users to 50MB uploads—then respond with 413 Request Entity Too Large
because the request body is larger than the server is willing to process. Again, the client could avoid this by using a LBYL request.
Likewise, if the server doesn’t want to support the video/mp4
media type, then it should respond with a 415 Unsupported Media Type
status code. A LBYL request would have told us this, as well.
I’ve already discussed 416 Requested Range Not Satisfiable
in a post about range requests and 417 Expectation Failed
in a post about the 100 Continue
status code.
Finally, we are all familiar with the 404 Not Found
status code. I mentioned it earlier in this post. The 404 Not Found
status, however, doesn’t tell the client whether the condition is temporary or permanent. It’s a pretty generic “I can’t find it” message. If you know that the resource is gone permanently, you may want to return a 410 Gone
status code, instead, as a way of letting smart clients (like search engines) know that they should remove all links to the resource. If the resource has moved permanently, though, I recommend using a 301 Moved Permanently
status, which will also tell these smart clients to update their links. How you choose to inform clients of the fate of your resources is up to you, but it’s in your best interest to tell them whether the data has moved or is gone and is no longer available.
I also mentioned the 404 Not Found and 410 Gone statuses when discussing the 201 Created
and 202 Accepted
status codes.