ChatGPT解决这个技术问题 Extra ChatGPT

400 vs 422 response to POST of data

I'm trying to figure out what the correct status code to return on different scenarios with a "REST-like" API that I'm working on. Let's say I have an end point that allows POST'ing purchases in JSON format. It looks like this:

{
    "account_number": 45645511,
    "upc": "00490000486",
    "price": 1.00,
    "tax": 0.08
}

What should I return if the client sends me "sales_tax" (instead of the expected "tax"). Currently, I'm returning a 400. But, I've started questioning myself on this. Should I really be returning a 422? I mean, it's JSON (which is supported) and it's valid JSON, it's just doesn't contain all of the required fields.


C
Community

400 Bad Request would now seem to be the best HTTP/1.1 status code for your use case.

At the time of your question (and my original answer), RFC 7231 was not a thing; at which point I objected to 400 Bad Request because RFC 2616 said (with emphasis mine):

The request could not be understood by the server due to malformed syntax.

and the request you describe is syntactically valid JSON encased in syntactically valid HTTP, and thus the server has no issues with the syntax of the request.

However as pointed out by Lee Saferite in the comments, RFC 7231, which obsoletes RFC 2616, does not include that restriction:

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).

However, prior to that re-wording (or if you want to quibble about RFC 7231 only being a proposed standard right now), 422 Unprocessable Entity does not seem an incorrect HTTP status code for your use case, because as the introduction to RFC 4918 says:

While the status codes provided by HTTP/1.1 are sufficient to describe most error conditions encountered by WebDAV methods, there are some errors that do not fall neatly into the existing categories. This specification defines extra status codes developed for WebDAV methods (Section 11)

And the description of 422 says:

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.

(Note the reference to syntax; I suspect 7231 partly obsoletes 4918 too)

This sounds exactly like your situation, but just in case there was any doubt, it goes on to say:

For example, this error condition may occur if an XML request body contains well-formed (i.e., syntactically correct), but semantically erroneous, XML instructions.

(Replace "XML" with "JSON" and I think we can agree that's your situation)

Now, some will object that RFC 4918 is about "HTTP Extensions for Web Distributed Authoring and Versioning (WebDAV)" and that you (presumably) are doing nothing involving WebDAV so shouldn't use things from it.

Given the choice between using an error code in the original standard that explicitly doesn't cover the situation, and one from an extension that describes the situation exactly, I would choose the latter.

Furthermore, RFC 4918 Section 21.4 refers to the IANA Hypertext Transfer Protocol (HTTP) Status Code Registry, where 422 can be found.

I propose that it is totally reasonable for an HTTP client or server to use any status code from that registry, so long as they do so correctly.

But as of HTTP/1.1, RFC 7231 has traction, so just use 400 Bad Request!


Your answer (422) makes sense to me. This is also what Rails (respond_with) uses when a resource couldn't be processed because of validation errors.
Note the use of 422 in non-WebDAV spec here: tools.ietf.org/html/rfc5789#section-2.2
Just as an update, RFC 7231 has a different description for response code 400 that changes the semantics.
My apologies - I updated this answer to reflect the change in RFCs and lost some clarity; I'll try to refactor. It is almost certainly safe to use 422, but nowadays you should use 400.
I still think the spec could be a lot clearer. The examples given in the are clear cases of the client doing something wrong. The OP's situation also falls into that category. However, there are cases like "I understand what you're asking, but I refuse to do it because there is some business rule against it" is not so clear cut. It's not exactly the client's fault, so a 403 might actually apply, per the same spec: "However, a request might be forbidden for reasons unrelated to the credentials". I'd prefer to have separate codes for permission related stuff vs "it cannot be done" though.
C
Ciro Santilli Путлер Капут 六四事

Case study: GitHub API

https://docs.github.com/en/rest/overview/resources-in-the-rest-api#client-errors

Maybe copying from well known APIs is a wise idea:

There are three possible types of client errors on API calls that receive request bodies: Sending invalid JSON will result in a 400 Bad Request response: HTTP/1.1 400 Bad Request Content-Length: 35 {"message":"Problems parsing JSON"} Sending the wrong type of JSON values will result in a 400 Bad Request response: HTTP/1.1 400 Bad Request Content-Length: 40 {"message":"Body should be a JSON object"} Sending invalid fields will result in a 422 Unprocessable Entity response: HTTP/1.1 422 Unprocessable Entity Content-Length: 149 { "message": "Validation Failed", "errors": [ { "resource": "Issue", "field": "title", "code": "missing_field" } ] }


Can't upvote it more. Wish that more upvoted answers would refer to this one. The specs (RFC, IANA) epically failed to provide clear definitions and distinction between the two. So the answer boils down to best practices and GitHub gives us one.
This has to be the accepted answer. Also, the url provided in the answer does no longer work and takes you to homepage. The latest url is : docs.github.com/en/rest/overview/….
So 422 is correct if e.g. "price" or "tax" hadn't been valid numbers? Basically violating the schema expected. Or if you tried to bill someone not in your system and you only bill people that are registered customers?
C
Community

400 Bad Request is proper HTTP status code for your use case. The code is defined by HTTP/0.9-1.1 RFC.

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

https://www.rfc-editor.org/rfc/rfc2616#section-10.4.1

422 Unprocessable Entity is defined by RFC 4918 - WebDav. Note that there is slight difference in comparison to 400, see quoted text below.

This error condition may occur if an XML request body contains well-formed (i.e., syntactically correct), but semantically erroneous, XML instructions.

To keep uniform interface you should use 422 only in a case of XML responses and you should also support all status codes defined by Webdav extension, not just 422.

https://www.rfc-editor.org/rfc/rfc4918#page-78

See also Mark Nottingham's post on status codes:

it’s a mistake to try to map each part of your application “deeply” into HTTP status codes; in most cases the level of granularity you want to be aiming for is much coarser. When in doubt, it’s OK to use the generic status codes 200 OK, 400 Bad Request and 500 Internal Service Error when there isn’t a better fit.

How to Think About HTTP Status Codes


422 code is part of IANA registry iana.org/assignments/http-status-codes/http-status-codes.xhtml so any IMHO have no sense. In any case Facebook and Twitter REST API reinvent own codes and don't use RFC/IANA standards. So you can do.
Section 11 specifically states they are added to the entire spec and not just within the WebDav spec: The following status codes are added to those defined in HTTP/1.1 [RFC2616].
Just because the code is described as part of the WebDAV spec doesn't mean it's WebDAV-specific! Status codes are supposed to be generic.
C
Community

To reflect the status as of 2015:

Behaviorally both 400 and 422 response codes will be treated the same by clients and intermediaries, so it actually doesn't make a concrete difference which you use.

However I would expect to see 400 currently used more widely, and furthermore the clarifications that the HTTPbis spec provides make it the more appropriate of the two status codes:

The HTTPbis spec clarifies the intent of 400 to not be solely for syntax errors. The broader phrase "indicates that the server cannot or will not process the request due to something which is perceived to be a client error" is now used.

422 is specifically a WebDAV extension, and is not referenced in RFC 2616 or in the newer HTTPbis specification.

For context, HTTPbis is a revision of the HTTP/1.1 spec that attempts to clarify areas that were unclear or inconsistent. Once it has reached approved status it will supersede RFC2616.


Doesn't the 403 Forbidden might also be used for this context then? Quote: The 403 (Forbidden) status code indicates that the server understood the request but refuses to authorize it...If authentication credentials were provided in the request, the server considers them insufficient to grant access....However, a request might be forbidden for reasons unrelated to the credentials. So it looks like 403 can be used to reject requests outside of authentication.
@garbagecollector note that "rejected for reasons outside of credentials" != "rejected for reasons outside of authentication." There are lots of ways to authenticate someone without using credentials, specifically.
@garbagecollector no, credentials means authentication ("who are you"), which would be 401 upon failure. Authorisation ("what can you do") would be 403 upon failure. Full explanation here: stackoverflow.com/a/6937030/137948 Neither apply to the OP's "missing fields" situation because the error would be the same regardless of which user attempted it. I agree 400 is the right answer.
c
cdeszaq

There is no correct answer, since it depends on what the definition of "syntax" is for your request. The most important thing is that you:

Use the response code(s) consistently Include as much additional information in the response body as you can to help the developer(s) using your API figure out what's going on.=

Before everyone jumps all over me for saying that there is no right or wrong answer here, let me explain a bit about how I came to the conclusion.

In this specific example, the OP's question is about a JSON request that contains a different key than expected. Now, the key name received is very similar, from a natural language standpoint, to the expected key, but it is, strictly, different, and hence not (usually) recognized by a machine as being equivalent.

As I said above, the deciding factor is what is meant by syntax. If the request was sent with a Content Type of application/json, then yes, the request is syntactically valid because it's valid JSON syntax, but not semantically valid, since it doesn't match what's expected. (assuming a strict definition of what makes the request in question semantically valid or not).

If, on the other hand, the request was sent with a more specific custom Content Type like application/vnd.mycorp.mydatatype+json that, perhaps, specifies exactly what fields are expected, then I would say that the request could easily be syntactically invalid, hence the 400 response.

In the case in question, since the key was wrong, not the value, there was a syntax error if there was a specification for what valid keys are. If there was no specification for valid keys, or the error was with a value, then it would be a semantic error.


Very underrated answer - thanks for the well worded explanation.
Exactly my thoughts on the matter! I'm coming from XML SOAP background and concept of schema just got into my blood and JSON documents rather don't announce their schema. To me it's whether server "understands" the request or not. If server doesn't know what "sales_tax" is then it's simply 400: "I have no idea what you sent me but definitely not what I want.".
Thank you, now understood which one I should use.
C
Clojurevangelist

422 Unprocessable Entity Explained Updated: March 6, 2017 What Is 422 Unprocessable Entity? A 422 status code occurs when a request is well-formed, however, due to semantic errors it is unable to be processed. This HTTP status was introduced in RFC 4918 and is more specifically geared toward HTTP extensions for Web Distributed Authoring and Versioning (WebDAV). There is some controversy out there on whether or not developers should return a 400 vs 422 error to clients (more on the differences between both statuses below). However, in most cases, it is agreed upon that the 422 status should only be returned if you support WebDAV capabilities. A word-for-word definition of the 422 status code taken from section 11.2 in RFC 4918 can be read below. 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. The definition goes on to say: For example, this error condition may occur if an XML request body contains well-formed (i.e., syntactically correct), but semantically erroneous, XML instructions. 400 vs 422 Status Codes Bad request errors make use of the 400 status code and should be returned to the client if the request syntax is malformed, contains invalid request message framing, or has deceptive request routing. This status code may seem pretty similar to the 422 unprocessable entity status, however, one small piece of information that distinguishes them is the fact that the syntax of a request entity for a 422 error is correct whereas the syntax of a request that generates a 400 error is incorrect. The use of the 422 status should be reserved only for very particular use-cases. In most other cases where a client error has occurred due to malformed syntax, the 400 Bad Request status should be used.

https://www.keycdn.com/support/422-unprocessable-entity/


C
Community

Your case: HTTP 400 is the right status code for your case from REST perspective as its syntactically incorrect to send sales_tax instead of tax, though its a valid JSON. This is normally enforced by most of the server side frameworks when mapping the JSON to objects. However, there are some REST implementations that ignore new key in JSON object. In that case, a custom content-type specification to accept only valid fields can be enforced by server-side.

Ideal Scenario for 422:

In an ideal world, 422 is preferred and generally acceptable to send as response if the server understands the content type of the request entity and the syntax of the request entity is correct but was unable to process the data because its semantically erroneous.

Situations of 400 over 422:

Remember, the response code 422 is an extended HTTP (WebDAV) status code. There are still some HTTP clients / front-end libraries that aren't prepared to handle 422. For them, its as simple as "HTTP 422 is wrong, because it's not HTTP". From the service perspective, 400 isn't quite specific.

In enterprise architecture, the services are deployed mostly on service layers like SOA, IDM, etc. They typically serve multiple clients ranging from a very old native client to a latest HTTP clients. If one of the clients doesn't handle HTTP 422, the options are that asking the client to upgrade or change your response code to HTTP 400 for everyone. In my experience, this is very rare these days but still a possibility. So, a careful study of your architecture is always required before deciding on the HTTP response codes.

To handle situation like these, the service layers normally use versioning or setup configuration flag for strict HTTP conformance clients to send 400, and send 422 for the rest of them. That way they provide backwards compatibility support for existing consumers but at the same time provide the ability for the new clients to consume HTTP 422.

The latest update to RFC7321 says:

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).

This confirms that servers can send HTTP 400 for invalid request. 400 doesn't refer only to syntax error anymore, however, 422 is still a genuine response provided the clients can handle it.


佚名

Firstly this is a very good question.

400 Bad Request - When a critical piece of information is missing from the request

e.g. The authorization header or content type header. Which is absolutely required by the server to understand the request. This can differ from server to server.

422 Unprocessable Entity - When the request body can't be parsed.

This is less severe than 400. The request has reached the server. The server has acknowledged the request has got the basic structure right. But the information in the request body can't be parsed or understood.

e.g. Content-Type: application/xml when request body is JSON.

Here's an article listing status codes and its use in REST APIs. https://metamug.com/article/status-codes-for-rest-api.php


422 means that the syntax is valid, but the contents are not. Sending JSON where XML is expected means that the syntax is wrong, so a 400 is the correct response in this case.
Exactly as Dirk said 422 means syntactically valid request (can be parsed and understood) but semantically invalid
400: when the request can't be processed because of invalid syntax (e.g. parsing error); 422: when the request can't be processed because of invalid data (e.g. validation error).
Your example for 422 is not valid because by sending json with an application/xml media type, the body automatically is syntactically incorrect and the response should be 400.