48

Say that I have a REST endpoint that takes an integer as a parameter:

/makeWaffles?numberOfWaffles=3

In this case, I want the number to be positive because I can't make a negative number of waffles (and requesting 0 waffles is a waste of time). So I want to reject any request that does not contain a positive integer. I also want to reject a request that exceeds some maximum integer (let's say for now that it's MAX_INTEGER).

In the event that someone requests a non-positive number of waffles, should I return an HTTP 400 (Bad Request) status? My initial thought is yes: it is not a valid number for me to complete the request. However, the RFC doesn't mention business rules as a reason to throw it:

The 400 (Bad Request) status code indicates that the server cannot or will not process the request due to something that is perceived to be a client error (e.g., malformed request syntax, invalid request message framing, or deceptive request routing).

A business rule doesn't fall under any of those three examples. It's syntactically correct, it's properly framed, and it's not deceptive request routing.

So should I return an HTTP 400 (Bad Request) status if a parameter is syntactically correct, but violates a business rule? Or is there a more appropriate status to return?

31

This is a great question, and still highly relevant given the historical context (and seemingly contradictory definitions) of the HTTP return codes. Even among the answers to this question there are conflicting definitions. This can be clarified by moving chronologically.

RFC 2616 (June 1999)

10.4.1 400 Bad Request

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

As of this RFC, this status code specifically applied only to syntactically invalid requests. There was a gap in the status codes for semantic validation. Thus, when RFC 4918 came around, a new code was born.

RFC 4918 (June 2007)

11.2. 422 Unprocessable Entity

The 422 (Unprocessable Entity) status code means the server understands the content type of the request entity (hence a 415(Unsupported Media Type) status code is inappropriate), and the syntax of the request entity is correct (thus a 400 (Bad Request) status code is inappropriate) but was unable to process the contained instructions. For example, this error condition may occur if an XML request body contains well-formed (i.e., syntactically correct), but semantically erroneous, XML instructions.

422 Unprocessable Entity was created to fill the gap of semantic validation in the original specification of the 4xx status codes. However, another relevant RFC came about in 2014 which generalized 400 to no longer be specific to syntax.

RFC 7231 (June 2014, explicitly obsoletes RFC 2616)

6.5.1. 400 Bad Request

The 400 (Bad Request) status code indicates that the server cannot or will not process the request due to something that is perceived to be a client error (e.g., malformed request syntax, invalid request message framing, or deceptive request routing).

Note that the 422 description says that the reason 400 is inappropriate is because 400 (as of RFC 2616) should be returned only for bad request syntax. However, as of RFC 7231, the strict syntax-error definition no longer applies to 400.

Back to the question at hand: While 422 is technically more specific, given this context, I could see either 400 or 422 being used for semantic validation of API parameters. I'm hesitant to use 422 in my own APIs because the definition of 422 is technically outdated at this point (although I don't know if that's officially recognized anywhere). The article referenced in Fran's answer that encourages the use of 422 was written in 2012, two years before RFC 7231 clarified HTTP 400. Just be sure to standardize on one or the other.

41

I read the first answer and didn't really agree with it because, at least in my reading, a bad request (400) means, "I can't even handle your request because something is fundamentally wrong." And I found this post which makes the case for returning a 422.

from IETF

422 Unprocessable Entity (WebDAV; RFC 4918) The request was well-formed but was unable to be followed due to semantic errors

This seems like a more appropriate response since your request is well-formed, but doesn't pass your validation rules.

  • 5
    Ive heard it described as "400 means bad syntax, 422 means bad semantics." – cbojar Aug 24 '16 at 20:44
  • 31
    All the x00 codes are "catch all" generic codes. A 400 is not inappropriate, just less specific. – Jack Aug 24 '16 at 21:11
  • Good answer, but the ansewer given by @GoFree makes more sense for me. – Ewerton Aug 30 '17 at 14:30
  • 1
    There is a really strong case for returning codes that everyone knows. Absolutely everyone will need to look up 422, and I'll bet that most still won't know what to make of it. – sylvanaar Feb 26 '18 at 17:11
8

Yes, input that doesn't follow the implied contract of the endpoint is "something perceived to be a client error", and should return 400.

The exceptions to this is if the business rule is security related (then 401 Unauthorized or 403 Forbidden would be better). Alternatively, if sending a 400 would leak information about something's existence, and then a 404 Not Found may be more appropriate.

8

No, you should not. HTTP codes are meant for the HTTP layer of your application. Business rules is completely different layer and is application specific, so you need to come up with your own "protocol".

Imagine an apocalypse happens and you have to switch from HTTP protocol to using Pigeons. Pigeons don't have any return codes, so you would need to change your business layer to accomodate for that. But your business has not really changed in any way so you shouldn't need to change business layer. It shows a tight coupling between those two layers (transport and business).

Back to the question: What you should do is return "200 OK" with a body describing what happened with the request. The specification clearly says so:

https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.2.1.

200 OK

The request has succeeded. The information returned with the response is dependent on the method used in the request, for example

POST an entity describing or containing the result of the action;

Has your HTTP request succeeded? Yes it has, the web server knows what to do with that request (e.g. pass it on to the server part of your application). Web server then passes this request to the server part of your application, which takes the POSTed data, processes them (validates them in your case) and returns a normal answer (in the body of an HTTP response) to the client part of your application. This answer from the server part of application can be either "Great, the data you sent me are valid" or "I'm sorry, the data you sent are not valid". And it is up to your client part of application to understand what the answer means.

PS: "400 Bad Request" means, that the web server did not understand what you want from it. It means that your server part of your application did not even receive the request. Or at least that's what it's meant to mean :-)

EDIT: I just realized, that you're doing GET request, not POST. This is a bad idea because GET should not change the state of the application. GET is supposed to simply retrieve data from the server. But in your request you are actually changing the state of the application, so you should really be using POST.

  • 1
    Yes, returning 404 in that case is fine. I'm not saying that server should always send 200 OK with an explanation in the body. – GoFree Mar 7 '17 at 23:27
  • Better explanation i seen so far. I have this same question and seems that all the word thinks differente from me and you @GoFree – Ewerton Aug 30 '17 at 14:27
  • @GoFree This is a really good answer to rethink API Design. But isn't it the case, that we use HTTP and its response code as eminent part of the business rules layer when we use a REST API? – Thomas Lauria Feb 14 at 7:27
  • 1
    @Thomas Lauria I haven't seen a proper implementation of RESTFUL API yet. However, REST API is a buzzword today so every company has to use it (the word, not the technology) without actually understanding the concept behind it. So yes, it's being used in a wrong way everywhere. What programmers usually create is not a REST API, but HTTP API, or API OVER HTTP. Actually one of the few good RESTFUL implementations is the HTTP itself :) – GoFree Feb 15 at 10:56
-3

Not sure that all would agree, but we are using 409 - Conflict. Many state the 409 is more of a conflict with system state, but we accepted the interpretation that a conflict of data values being outside of accepted range is fixable by the requester and an acceptable use of 409. 422 I think would be reasonable as the request is correctly formed but cannot be processed as requested. I opine however if you do not wish to implement a host of replies, just giving a 400 is still acceptable.

  • 5
    409 means "the state you're trying to put this in is in conflict with the state another client is trying to put this in", it's for blocking concurrent writes (using ETags, for example) – Jack Aug 24 '16 at 21:12

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.