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-requ...@lists.openstack.org?subject:unsubscribe > http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev > -- Ryan Brown / Software Engineer, Openstack / Red Hat, Inc. __________________________________________________________________________ OpenStack Development Mailing List (not for usage questions) Unsubscribe: openstack-dev-requ...@lists.openstack.org?subject:unsubscribe http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev