503, 403 & Retry-After: enforcing a limit on the number of requests allowed

I've been wondering about the response code to use for enforcing a limit 
on the number of requests allowed.

Say I allow 10 requests per minute from a certain IP address. After 20 
seconds, my server receives an 11th request from a client and needs to 
reject it, as advertised to the client.

503 ("The server is currently unable to handle the request due to a 
temporary overloading or maintenance of the server.") is tempting 
because of the Retry-After header: the server can tell the client to try 
again in 40 seconds. However, the server has not really failed to 
process the request, it *chose* not to process it, because the client 
did something it should not have done.

So using a 5xx error code seems wrong, and a 4xx response more 
appropriate: the client was told not to do more than 10 requests a 
minute, but sent an 11th one, and therefore it's its fault that the 
request is not processed by the server which is behaving perfectly 
normally from that POV.

403 could work ("The server understood the request, but is refusing to 
fulfill it."). However 403 implies that "the request SHOULD NOT be 
repeated". Moreover, the Retry-After header is not defined for 4xx 
response codes as per section 14.37 to hint that the request could be 
repeated, and tell the client when it is acceptable to retry the 
request. So it's not very well suited.

So the options I see today are:
- use a server error (503) along with the Retry-After header
- use a client error (403), and convey when the request can be retried 
in the entity body (which is sub-optimal)

A better solution would be to allow Retry-After on a 403, with the 
meaning that the request can be retried at a later point, as indicated.

Cheers,

Hugo

Received on Wednesday, 6 February 2008 19:05:41 UTC