400 vs 422 response to POST that references an unk

2020-02-26 00:35发布

问题:

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.

This example is borrowed from another question about syntax type issues in the body, but my question assumes valid syntax throughout.

Let's say I have an endpoint that allows POST'ing purchases in JSON format. It looks like this:

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

What is the appropriate status code if:

  • the account number does not exist
  • the account is closed or the
  • account identified is not the right kind of account

These are all firmly business layer issues that prevent "processing" from occuring, hwoever, one scenario involves something that in a GET would be a 404.

Note that the account number is not in the URL, so is 404 misleading?

回答1:

Let's take these one at a time. Each of these codes is a signal to your client that the server is functioning correctly, and that something must be changed in the request before it can be successfully carried out.

  • HTTP 400

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

400 typically indicates a syntax error; as a user, I should look at the structure of the request before trying again.

  • HTTP 404

The server has not found anything matching the Request-URI. No indication is given of whether the condition is temporary or permanent. The 410 (Gone) status code SHOULD be used if the server knows, through some internally configurable mechanism, that an old resource is permanently unavailable and has no forwarding address. This status code is commonly used when the server does not wish to reveal exactly why the request has been refused, or when no other response is applicable.

404 is the standard code used when a web server can't match a url path to anything. As a client, I should look at the URL of the request before trying again.

  • HTTP 422

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 is generally used for content violations. As a user, I should look at the content of my request before trying again.

Now in your case, account number is an identifying number, but is not included in the URL. A 404 would signal to your user that the URL is wrong, not the payload. Stated another way, suppose your url is:

http://www.myservice.net/endpoint

A 404 would indicate to me that no service exists at /endpoint, instead of no account number. No matter what content I submit, the server will not process my request. The fix I should make then would be to look for an error in the URL, instead of the data payload. So to me a 422 would point me in the right direction, unless you begin to include the account number in the URL.

Ultimately these are design preferences, just make sure you communicate them clearly to your users.



回答2:

If you consider the accounts to be part of the state of the resource (though indirectly) then you might also consider 409 since that state is in conflict with the semantics of the request.

However, 422 is gaining popularity via Ruby on Rails and Dropwizard where it is used to indicate non-syntactic issues with the body. That growing tendency represents a strong signal to a developer using the API that they need to exclude syntax and focus on the body. Developer time is usually the single largest cost your customers will ever incur, so by directing the attention of their developers you will keep them happy.

So 409 is a possible answer, though rather novel, and 422 is the more conventional approach, although obviously RoR and DropWizard are both rather new so these conventions can be said to be changing fast!



回答3:

I'd say 422 is adequate in your case, but 400 isn't bad if it's consistent with the rest of your API. It's a common convention to use 400 as an umbrella error code when there's something wrong on the client side, but either the error doesn't fit a particular error code, or you don't want to use too many of them.

A 404 is definitely wrong if there's something wrong with the POST payload.



回答4:

Case 1 : Account number doesn't exist. This is a standard case for 404.

Case 2 : Account is closed. This has do with the logic if you keep the account details when you close it. If you donot keep the account details when the account is closed, you can give 404. If you keep the account details after it is closed, you must be marking it (like raising some flag) (or whatever logic you have). In this case, Status code 400 with a proper message of why it is failed and possibly remediation will do.

Case 3 : Account identified is not the right kind of account. 403, as the account is not authorised for completing any purchases makes sense to me. If there is no concept like authorised account, 400 with a explanatory message will do. But I would insist to go with 403 in this case.



回答5:

Actually, in this case 404 sounds good to me.



标签: rest