HTTP status for different conflict scenarios

2019-08-12 14:23发布

问题:

I'm implementing user registration for a Web Service.

When somebody wants to register an account, my WS sends an activation link to his/her mail. Until this link is clicked, user account is not activated (but the info is persisted in database, so the resource exists).

So my question is, if you try to register the same mail several times, you will get a 409 CONFLICT code. But there are two scenarios right there:

  1. User account pending on confirmation
  2. User already registered and activated

I would like to know what is the right approach. Should I "invent" an HTTP status 4XX to distinguish them, or send 409 with a JSON with info? other solutions?

Thx!

EDIT:

I have found this response -> https://stackoverflow.com/a/3290369/1171280 where Piskvor suggest to use 409 status and request header to explain the reason why it failed and/or body. Which one? header? body? both?

What do you think?

EDIT 2:

HTTP status + body with detailed error (with machine-parseable codes even) is OK, Twitter does that (https://dev.twitter.com/docs/error-codes-responses) and RESPECT :) . But I still doubt with 403 vs 409... :S

回答1:

Pending account is a special type of a user account, so I think both accounts (already registered and pending) are same in the context of your question. You should return 409 in both cases. For the REST API both are same cases because that resource already exists in the system.

Regarding your updated question, I would suggest using body (JSON) to send out error(s) instead of using a custom HTTP header to explain the reason why the call failed. Reason is that in the body can you have multiple error messages (each one as a separate JSON object/array element) where as in the header you can have only one (though you can split based on some character). Other reason is that you can have one generic error handling method which looks for an "error" object in the JSON instead of looking for different custom headers for each failure scenario.

HTTP codes:

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

409 - The request could not be completed due to a conflict with the current state of the resource. This code is only allowed in situations where it is expected that the user might be able to resolve the conflict and resubmit the request.

I think it should be 409 because the conflict can be resolved by re-issuing the request with different email address.



回答2:

HTTP status codes are not meant to "invented".

409 CONFLICT sounds OK to me. Including details in the body ist OK, too, if your client needs to know.



回答3:

Don't use 409. Use 403.

[409] is only allowed in situations where it is expected that the user might be able to resolve the conflict and resubmit the request.

It's for a request that should have been OK, but has a problem that can be resolved. If you edit a document and PUT the revised text but someone else did the same thing before you did, you should have a chance to look at the other person's work so you don't accidentally undo all their work. You'd get a 409 which means, if you want to revise it, you should send your revision with an indication that you've seen the latest revision by the other person -- i.e. you know what you're doing.

There's no way to 'correct' a redundant attempt to register. The only way to avoid the conflict is to register with a different username, but that's very incorrect.

I'm imagining a POST request that takes a username and email address and creates a new resource dedicated to that new user (which should now be used for validation), sending that resource's URL in an email. So you're dealing with the refusal of the POST request handler to create a new resource, for a reason specific to the business model of your application (rather than an HTTP-related reason like bad syntax).

There's no status code more specific to what you want than 403. In this case, all you should use HTTP's vocabulary to communicate is 'that's not allowed' -- use the layer on top of HTTP to communicate why, like a polite HTML page or a JSON object for the client to understand and render as a polite HTML page.



回答4:

409 should be ok; for the details http://tools.ietf.org/html/draft-nottingham-http-problem-04 might be of interest.