The implication from the change is that we also need to remove 400
from the StatusCodeRedirect middleware. On a related note, the
following bits of code (from 0.9.7 beta5) seems to be inconsistent
with the comment:
# Display error documents for 401, 403, 404 status codes (and
# 500 when debug is disabled)
if asbool(config['debug']):
app = StatusCodeRedirect(app)
else:
app = StatusCodeRedirect(app, [400, 401, 403, 404, 500])
Regards,
Yap
Returning 400 for form validation error is recommended by Leonard
Richardson and Sam Ruby in the book RESTful Web Services. Here's an
excerpt from one of the examples in the book:
"If the client sends bad or incomplete data, the ActiveRecord
validation rules (defined in the User) model) fail, and the call to
User#save returns false. The response code then is 400 ("Bad
Request")."
Also, according to the specifications for OpenID and OAuth, both of
them return 400 for bad or missing parameters. I don't see any
difference between an OAuth service provider implemented using pylons
and my custom pylons web app. If the former shall return 400 for bad
or missing parameters, why can't the later?
By the way, structs has a bug report for the same issue that was
resolved as "Not A Problem", forcing their users to resort to
subclassing. So I guess it's OK if you don't like the idea :)
Regards,
Yap
Of course, I mean struts instead of structs. Here's the URL:
https://issues.apache.org/struts/browse/STR-2119
Also if they didn't say it... it's just that 200 OK is plain wrong to
signal an error condition.
That's what 4xx and 5xx codes are for.
--
Lawrence, stacktrace.it - oluyede.org - neropercaso.it
"It is difficult to get a man to understand
something when his salary depends on not
understanding it" - Upton Sinclair
Building up on the json example, it should be read as, the request was
successful and everything when ok (http:200) now it seems you fail
with supplying the correct values (statusCode:xxx)
as for the webservices reference, I don't think that applies to
web-browsers, they could even interpret the 400 as something totally
different.
That said if enough people find this useful I'll say add a config
option where you can switch it and leave it as 200 for default.
I disagree. TCP is the transport protocol (which resides at the
transport level of the stack).
HTTP is an application protocol (which resides on top of the stack),
and I'm pretty sure that
the creators of HTTP intended to use 400 BAD REQUEST also for such
cases. As the spec says:
" The request could not be understood by the server due to malformed
syntax. The client SHOULD NOT repeat the request without
modifications. "
Nothing forbids to explain _why_ in the body of the response but if
you want to create a seamless web where 200 means "ok what you asked
worked correctly"
returning 200 for an error is not the most compatible way to go.
Remember also there are automatic clients, non-desktop-web clients,
mobile browsers and so on.
If you want maximum compatibility I think that returning an error code
for an error situation is not also smart to do but should be
mandatory.
There is really no point in returning a OK status code with something
that didn't go as it should.
Imagine a situation when I do subsequently PUT of a resource like
/book/summer. If the server replied 200 with a wrong content (or wrong
content type) how do I know
that I'm doing something wrong? Looking at the body searching for the
"error" word is not feasible, that's what status codes are for.
> Building up on the json example, it should be read as, the request was
> successful and everything when ok (http:200) now it seems you fail
> with supplying the correct values (statusCode:xxx)
So the request did not suceed because the GOAL was not to test that
the server is there and alive but that the next time I access to the
resource it will be there.
Not that I'll found out in 10 minutes that the request I made 10
minutes ago didn't work altough the server told me it did.
That's quite byzarre.
> as for the webservices reference, I don't think that applies to
> web-browsers, they could even interpret the 400 as something totally
> different.
Web browser are web clients of web services. There shouldn't
definitely be a difference in status codes among which kind of client
I could get.
There can be a difference in response format (based on Accept or
suffixes) but it's insane to return different status codes based on
the UserAgent.
It reminds of the old day of UA sniffing to render different pages.
My suggestion is to read something about HTTP and REST in general.
Why bend the rules when these are the basic scenarios where HTTP shines?
I can be wrong about the correct status code but returning 200 for an
error situations is asking for troubles and asking for more and more
work for the people who needs to access that web service in the
future: be that a browser, a programming language, a mobile phone or
whatever.
Some web standards are so good because if you do things correctly they
can last and work with clients that are nowhere but in the minds of
future developers.
> I disagree. TCP is the transport protocol (which resides at the
> transport level of the stack).
> HTTP is an application protocol (which resides on top of the stack),
> and I'm pretty sure that
> the creators of HTTP intended to use 400 BAD REQUEST also for such
> cases. As the spec says:
>
> " The request could not be understood by the server due to malformed
> syntax. The client SHOULD NOT repeat the request without
> modifications. "
The "malformed syntax" they refer to is the HTTP protocol syntax (for
example, malformed, missing, or improperly escaped HTTP headers, URLs,
etc).
The key phrase here is "the request could not be understood by the
server".
If a form is missing a field, your server still understood (and could
process) the request, it's your application that refuses the request
because of its own requirements that are completely separate from the
requirements of the HTTP server.
Regards,
Cliff
Well, much of this problem is due to the same problem so much of the web
has in general: all-around bad planning and poor specifications. It
does seem rather inconsistent that a form shouldn't return a 40x but an
internal server error returns a 50x.
At the end of the day, I suppose it might be acceptable to return a 40x
if you consider POST data as part of the request (at the same level as
GET arguments are). So for instance it seems valid that:
returns a 40x and so a POST to
http://domain.com with a body of page=bar
should too. And once you accept that, it seems reasonable to include
any invalid POST data as a 40x as well. Shrug.
I reserve the right to reverse my position again after I've had another
beer.
Regards,
Cliff
No, on modern browsers, your form validation error page will still be
displayed. I have only tested with Opera and Firefox, but even IE6 can
do it if your page is larger than half a kb [1]
On 8/23/08, Cliff wrote:
>
> If a form is missing a field, your server still understood (and could
> process) the request, it's your application that refuses the request
> because of its own requirements that are completely separate from the
> requirements of the HTTP server.
>
When my app cannot locate a resource, it returns a 404.
When my app cannot recognize the user, it returns a 401.
When my app doesn't like the user, it returns a 403.
When my app thinks a request is broken, it returns a 400.
My app is the HTTP server.
By the way, Django has a rest plugin that is hardcoded to return 400
on form validation failures [2]. Struts has a rest plugin that by
default returns 400 on form validation failures [3]. Pylons already
has a wonderful rest controller. I am merely suggesting to add a
parameter to @validate that is defaulted to 200.
Regards,
Yap
[1] http://support.microsoft.com/kb/q218155/
[2] http://code.google.com/p/django-rest-interface/
[3] http://struts.apache.org/2.x/docs/rest-plugin.html
> By the way, Django has a rest plugin that is hardcoded to return 400
> on form validation failures [2]. Struts has a rest plugin that by
> default returns 400 on form validation failures [3]. Pylons already
> has a wonderful rest controller. I am merely suggesting to add a
> parameter to @validate that is defaulted to 200.
Yea..... @validate already has 4 too many options, there's no way it
should have any more, in fact, it shouldn't have as many as it does. ;)
It needs some serious re-working, likely as several decorators, or
options that can be combined in various ways, to avoid having a single
function with 10+ keyword options (eeeeek). There was a proposal
awhile back to split it up, I think that should be revisited. I see no
problem with making this an option for those that want it, we just
need it in a new validate setup.
Cheers,
Ben
abort(400, "required query param 'foo' missing")
On Fri, Aug 22, 2008 at 10:51 PM, Ben Bangert <b...@groovie.org> wrote:
> @validate already has 4 too many options, there's no way it should
> have any more, in fact, it shouldn't have as many as it does. ;)
>
> It needs some serious re-working, likely as several decorators, or options
> that can be combined in various ways, to avoid having a single function with
> 10+ keyword options (eeeeek). There was a proposal awhile back to split it
> up, I think that should be revisited. I see no problem with making this an
> option for those that want it, we just need it in a new validate setup.
http://pylonshq.com/project/pylonshq/ticket/405
I want to work on this when I have time because there are so many
cases where @validate is too monolithic. (E.g., need a database
record to validate against, don't need a whole validator class.) In
the meantime there's code in the ticket if somebody wants to try it
out.
--
Mike Orr <slugg...@gmail.com>
Remember that REST is just a vague concept like MVC. It just means to
use a meaningful URL structure. It' doesn't say what those URLs
should be, which HTTP methods to use, or what to name your controller
actions. map.resource/ATOM is a particular implementation of REST,
not REST itself.
map.resource makes a lot of sense for things that will be aggregated
or called by programs. It makes some sense for things that will be
called only through an interactive web browser, but there are
tradeoffs. Using pseudo-PUT and DELETE in web browsers is
questionable. Having a "/foos/1/edit" that PUTs to "/foos/1" is
funny; why not post to the same URL as the form? Why is there no
delete confirmation form ("/foos/1/ask-delete", which I add to every
resource). One of the things I want to add to Routes 2 is a
simplified add/modify/delete structure for cases where map.resource is
overkill. (And one that enables only specific actions; e.g., no
delete or no index.)
The other problem is nested resources.
"/incidents/123/entries/456/attachments/789/edit" is really long, and
fails to show the close relationship of an item to its id. With
non-numeric IDs, you may not even be able to tell which are items and
which are IDs. In my old site I had /123/456/edit, which made it
easier to see the whole URL in the location bar and to type it by
hand. But I wanted to do it the "right" way in Pylons, and nested
resources were too precarious and undocumented to be trusted, so I
ended up flattening the resources to /incidents/123 and /entries/456.
(All entry IDs were unique, so the latter worked.)
--
Mike Orr <slugg...@gmail.com>
Well, the thread is old and kind of closed, but just for the record I
think a 400 Bad Request code is entirely reasonable for this case, and a
good use of that response code, with little ill effect (assuming, as was
noted, that you respond with a large enough body to avoid the IE error
page).
--
Ian Bicking : ia...@colorstudy.com : http://blog.ianbicking.org