[openstack-dev] [api] Changing 403 Forbidden to 400 Bad Request for OverQuota was: [nova] Which error code should we return when OverQuota

Ryan Brown rybrown at redhat.com
Wed May 6 19:41:11 UTC 2015


On 05/06/2015 03:15 PM, Chris Dent wrote:
> On Wed, 6 May 2015, Jay Pipes wrote:
> 
>> I think Sean makes an excellent point that if you have >1 condition
>> that results in a 403 Forbidden, it actually does not make things more
>> expressive. It actually just means both humans and clients need to now
>> delve deeper into the error context to determine if this is something
>> they actually don't have permission to do, or whether they've exceeded
>> their quota but otherwise have permission to do some action.
> 
> As I said to Sean in IRC, I can see where you guys are coming from
> and I haven't really got a better counter-proposal than "my experience
> writing servers and clients doesn't like this" so it's not like I want
> to fight about it. I do think it is worth discussion and there are
> obviously costs either way that we should identify and balance.
> Interestingly, in the process of writing this response I think I've
> managed to come up with a few reasons. On the other hand maybe I'm
> just getting out yet more paint for the shed.
> 
> Basically it seems to me that the proposal to use 400 just moves the
> problem around, one option has conditionals localized under 400,
> centralizing the ambiguity. The other option puts the ambiguity in
> categories. I guess my brain works better with the latter: a kind of
> cascading decision tree.
> 
> Note: I think we're all perpetuating the myth or wish that we actually
> do do something in code in response to 400 errors. Maybe in some very
> special clients it might happen, but in ad-hoc clients (the best kind)
> for the most part we report the status and fail and let the human decide
> what's next.

Guilty as charged. It may be that the benefit of moving 403->400 isn't
worth the trouble in any case (though I'd prefer it) since there are
already clients out in the world that may/may not rely on this behavior.

> In that sort of context I want the response _codes_ to have some
> semantics because I want to branch on the codes (if I branch at all)
> and nothing else:
> 
> * 400: bro, something bogus happened, I'm pretty sure it was your
>        fault
> * 401: Tell me who you are and you might get to do this
> * 402: You might get to do this if you pay
> * 403: You didn't get to do this because the _server_ forbids you
> * 404: You didn't get to do this because it ain't there
> * 405: You didn't get to do this because that action is not available
> * 406: I've got the thing you want, but not in the form you want it
> * 407: Some man in the middle proxy needs auth
> * 408: You spoke too slowly for my awesome brains
> * 409: Somebody else got there first
> * 410: Seriously, it ain't there and it never will be
> * 411: Why u no content-length!?
> * 412: You sent conditional headers and I can't meet their
>        requirements
> * 413: Too big in the body!
> * 414: Too big in the URI!
> * 415: You sent me a thing and I might have been able to do
>        something with it if it were in a different form
> [...]
> 
> These all mean things as defined by rfcs 7231 and 7235. Those rfcs
> were not pulled out of thin air: They are part of the suite of rfcs
> that define HTTP. Do we want to do HTTP? Yes, I think so. In that case,
> we ought to follow it where possible.
> 
> Each of those codes above have different levels of ambiguity. Some
> are quite specific. For example 405, 406, 411, 412 and 415. Where we
> can be sure they are the correct response we should use them and
> most assuredly _not_ 400.
> 
> 403, as you've both identified, is a lot more squiffy: "the server
> understood the request but refuses to authorize it...a request
> might be forbidden for reasons unrelated to the credentials".
> 
> Which leads us to 400. How I tend to use 400 is when none of 405, 406,
> 409, 411, 412 or 415 can be used because the representation is
> _claiming_ legitimate form (based on the headers) and no conditionals
> are being violated and where none of 401, 403 or 404 can be used because
> the thing is there, I am authentic and the server is not forbidding .
> What that means is that there's some crufty about the otherwise good
> representation: You've claimed to be sending JSON and you did, but you
> left out a required field.
> 
> There is no other 4xx that covers that, thus 400.
> 
> Now if we try to meld my rules with this idea about signifying over
> quota, I feel we've now discovered some collisions:
> 
>     My use of 400 means "there's something wrong with your request".
>     This is also what the spec says: "the client seems to have erred".
> 
>     Both of these essentially say "that request was pretty okay, but not
>     quite right and you can change the _request_ (or perhaps the client
>     side environment) and achieve success".
> 
>     In the case of quota you need to change the server side environment,
>     not this request. In fact if you do change the server (your quota)
>     and then do the same request again it will likely work.
> 
>     Looking at 403 again: "the server understood the request but refuses
>     to authorize it".
> 

Very good point. I was thinking about it from the other direction: the
client asked for too much stuff (something wrong with the request) and
so a 400 seemed quite reasonable.

> 4xx means client side error ("The 4xx (Client Error) class of status
> code indicates that the client seems to have erred."), so arguably
> over quota doesn't really work in _any_ 4xx because the client made no
> error, the service just has a quota lower than they need. We don't
> want to go down the non 4xx road at this time, so given our choices
> 403 is the one that most says "the server won't have it". It doesn't
> really fit in with 4xx at all, just like over quota doesn't!
> -=-=-
> 
> Moving away from that specific issue I think it important that we
> get our use of HTTP right. Whether we use 403 or 400 for quota is
> not going to break the world. Using 400 for nearly everything,
> however, may because it will make us seem like yet another system
> that couldn't be bothered to do things correctly and, you know,
> there are enough of those out there. Let's not be one of those.
> 
> If we follow the global specs for HTTP (where possible) and not our
> own little derivations then we don't have to be responsible for
> creating and maintaining our own special rules, we just use the
> rules that exist.
> So yeah, my argument basically comes down to: There's a spec, let's
> follow it as much as possible.
> 
>> p.s. And, yes, Chris, I definitely do see your side of the coin on
>> this. It's nuanced, and a grey area...
> 
>  (╯°□°)╯︵ ┻━┻
> 
> (not really throwing a table, I just think it is fun to paste that
> rather evocative image)
> 
> 
> 
> __________________________________________________________________________
> OpenStack Development Mailing List (not for usage questions)
> Unsubscribe: OpenStack-dev-request at lists.openstack.org?subject:unsubscribe
> http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev
> 

-- 
Ryan Brown / Software Engineer, Openstack / Red Hat, Inc.



More information about the OpenStack-dev mailing list