400 BAD request HTTP error code meaning?

2018-12-31 07:01发布

I have a JSON request which I'm posting to a HTTP URL.

Should this be treated as 400 where requestedResource field exists but "Roman" is an invalid value for this field?

[{requestedResource:"Roman"}] 

Should this be treated as 400 where "blah" field doesn't exist at all?

[{blah:"Roman"}]

7条回答
无与为乐者.
2楼-- · 2018-12-31 07:22

A 400 means that the request was malformed. In other words, the data stream sent by the client to the server didn't follow the rules.

In the case of a REST API with a JSON payload, 400's are typically, and correctly I would say, used to indicate that the JSON is invalid in some way according to the API specification for the service.

By that logic, both the scenarios you provided should be 400's.

Imagine instead this were XML rather than JSON. In both cases, the XML would never pass schema validation--either because of an undefined element or an improper element value. That would be a bad request. Same deal here.

查看更多
弹指情弦暗扣
3楼-- · 2018-12-31 07:22

Using 400 status codes for any other purpose than indicating that the request is malformed is just plain wrong.

If the request payload contains a byte-sequence that could not be parsed as application/json (if the server expects that dataformat), the appropriate status code is 415:

The server is refusing to service the request because the entity of the request is in a format not supported by the requested resource for the requested method.

If the request payload is syntactically correct but semantically incorrect, the non-standard 422 response code may be used, or the standard 403 status code:

The server understood the request, but is refusing to fulfill it. Authorization will not help and the request SHOULD NOT be repeated.

查看更多
闭嘴吧你
4楼-- · 2018-12-31 07:23

From w3.org

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.

查看更多
旧人旧事旧时光
5楼-- · 2018-12-31 07:23

Think about expectations.

As a client app, you expect to know if something goes wrong on the server side. If the server needs to throw an error when blah is missing or the requestedResource value is incorrect than a 400 error would be appropriate.

查看更多
春风洒进眼中
6楼-- · 2018-12-31 07:26

Selecting a HTTP response code is quite an easy task and can be described by simple rules. The only tricky part which is often forgotten is paragraph 6.5 from RFC 7231:

Except when responding to a HEAD request, the server SHOULD send a representation containing an explanation of the error situation, and whether it is a temporary or permanent condition.

Rules are as following:

  1. If request was successful, then return 2xx code (3xx for redirect). If there was an internal logic error on a server, then return 5xx. If there is anything wrong in client request, then return 4xx code.
  2. Look through available response code from selected category. If one of them has a name which matches well to your situation, you can use it. Otherwise just fallback to x00 code (200, 400, 500). If you doubt, fallback to x00 code.
  3. Return error description in response body. For 4xx codes it must contain enough information for client developer to understand the reason and fix the client. For 5xx because of security reasons no details must be revealed.
  4. If client needs to distinguish different errors and have different reaction depending on it, define a machine readable and extendible error format and use it everywhere in your API. It is good practice to make that from very beginning.
  5. Keep in mind that client developer may do strange things and try to parse strings which you return as human readable description. And by changing the strings you will break such badly written clients. So always provide machine readable description and try to avoid reporting additional information in text.

So in your case I'd returned 400 error and something like this if "Roman" is obtained from user input and client must have specific reaction:

{
    "error_type" : "unsupported_resource",
    "error_description" : "\"Roman\" is not supported"
}

or a more generic error, if such situation is a bad logic error in a client and is not expected, unless developer made something wrong:

{
    "error_type" : "malformed_json",
    "error_description" : "\"Roman\" is not supported for \"requestedResource\" field"
}
查看更多
呛了眼睛熬了心
7楼-- · 2018-12-31 07:37

In neither case is the "syntax malformed". It's the semantics that are wrong. Hence, IMHO a 400 is inappropriate. Instead, it would be appropriate to return a 200 along with some kind of error object such as { "error": { "message": "Unknown request keyword" } } or whatever.

Consider the client processing path(s). An error in syntax (e.g. invalid JSON) is an error in the logic of the program, in other words a bug of some sort, and should be handled accordingly, in a way similar to a 403, say; in other words, something bad has gone wrong.

An error in a parameter value, on the other hand, is an error of semantics, perhaps due to say poorly validated user input. It is not an HTTP error (although I suppose it could be a 422). The processing path would be different.

For instance, in jQuery, I would prefer not to have to write a single error handler that deals with both things like 500 and some app-specific semantic error. Other frameworks, Ember for one, also treat HTTP errors like 400s and 500s identically as big fat failures, requiring the programmer to detect what's going on and branch depending on whether it's a "real" error or not.

查看更多
登录 后发表回答