Skip to content

Framework returns wrong response code (400) #4509

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
cochiseruhulessin opened this issue Sep 22, 2016 · 6 comments
Closed

Framework returns wrong response code (400) #4509

cochiseruhulessin opened this issue Sep 22, 2016 · 6 comments

Comments

@cochiseruhulessin
Copy link

cochiseruhulessin commented Sep 22, 2016

During certain error conditions, the django-rest-framework returns a wrong response code (400).

As per RFC 2616:

The request could not be understood by the server due to malformed syntax.
The client SHOULD NOT repeat the request without modifications.

This means that the syntax of the request entity is malformed, and has nothing to do with the request payload (django-rest-framework deals only with request payloads, not with parsing of the byte-stream producing the request).

Is there any way to override this behavior to create standard-conforming HTTP APIs using the django-rest-framework?

@rpkilby
Copy link
Member

rpkilby commented Sep 22, 2016

http://stackoverflow.com/questions/16133923/400-vs-422-response-to-post-of-data/20215807#20215807

In short, rfc 7231 obsoletes rfc 2616 and it's correct to use an http 400 response for validation errors.

@rpkilby
Copy link
Member

rpkilby commented Sep 22, 2016

If you want to override the response code anyway, there is this section in the docs on custom exception handling.

@cochiseruhulessin
Copy link
Author

RFC 7231 is a proposed standard, not a standard. And even if it was, this doesn't justify that the framework responds with a 400 response code when - for example - a unique constraint is violated and an exception is raised during validation (since in that case, the appropriate response code would be 409). These is no way to maintanably do this using a custom error handler (since you would have to inspect the error messages in non_field_errors).

@rpkilby
Copy link
Member

rpkilby commented Sep 22, 2016

It is technically a proposed standard, but is for all practical purposes the de facto standard. eg, the IANA points to rfc 7231 for the definition of the 400 status code.

See: http://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml

@tomchristie
Copy link
Member

when - for example - a unique constraint is violated and an exception is raised during validation (since in that case, the appropriate response code would be 409

  1. What status code would you expect when an error includes both uniqueness validation errors and non-uniqueness validation errors.
  2. What behavioral difference should a client be expected to make in response to 400 vs 409.

We allow plenty of scope for overriding the behavior here, but 400 is the most valid status code for validation errors.

@claytondaley
Copy link

claytondaley commented Sep 1, 2017

I'm sniffing around the 409 question. In case it gets revisited now or later, I want to address the valid questions included here:

What status code would you expect when an error includes both uniqueness validation errors and non-uniqueness validation errors.

I think the 400 trumps the 409. I don't think it makes sense to even compare an invalid client submission (400) to the current state of a resource (409). Just noticed this is actually the issue in #3381.

What behavioral difference should a client be expected to make in response to 400 vs 409.

The concurrency issue is the "easy" answer, but here's another example that's close to something we're actually doing:

  • Application components are distributed between server A and server B
  • Server A creates a message for a component on server B and stores it locally
  • We have a component that pushes the message from storage on A to storage on B
  • Assume we use a UUID as the primary key (same id on both sides) and push the messages over using a REST call
  • I send a message and a network issue causes the DB commit to succeed but the "ack" to fail.
  • I retry the message. If I get a 409, I know the message exists so I can mark it as transferred.
  • If I get a 400, I need to retry. For example, I may have upgraded one side of the connection but not the other. The problem is in the request an not its relation to the database.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants