HTTP response code for POST when resource already

2019-01-05 06:42发布

I'm building a server that allows clients to store objects. Those objects are fully constructed at client side, complete with object IDs that are permanent for the whole lifetime of the object.

I have defined the API so that clients can create or modify objects using PUT:

PUT /objects/{id} HTTP/1.1
...

{json representation of the object}

The {id} is the object ID, so it is part of the Request-URI.

Now, I'm also considering allowing clients to create the object using POST:

POST /objects/ HTTP/1.1
...

{json representation of the object, including ID}

Since POST is meant as "append" operation, I'm not sure what to do in case the object is already there. Should I treat the request as modification request or should I return some error code (which)?

标签: http rest
15条回答
地球回转人心会变
2楼-- · 2019-01-05 07:32

Stumbled upon this question while checking for correct code for duplicate record.

Pardon my ignorance but I don't understand why everyone is ignoring the code "300" which clearly says "multiple choice" or "Ambiguous"

In my opinion this would be the perfect code for building a non standard or a particular system for your own use. I could be wrong as well!

https://tools.ietf.org/html/rfc7231#section-6.4.1

查看更多
Luminary・发光体
3楼-- · 2019-01-05 07:33

"302 Found" sounds logical for me. And the RFC 2616 says that it CAN be answered for other requests than GET and HEAD (and this surely includes POST)

But it still keeps the visitor going to this URL to get this "Found" resource, by the RFC. To make it to go directly to the real "Found" URL one should be using "303 See Other", which makes sense, but forces another call to GET its following URL. On the good side, this GET is cacheable.

I think that I would use "303 See Other". I dont know if I can respond with the "thing" found in the body, but I would like to do so to save one roundtrip to the server.

UPDATE: After re-reading the RFC, I still think that an inexistent "4XX+303 Found" code should be the correct. However, the "409 Conflict" is the best existing answer code (as pointed by @ Wrikken), maybe including a Location header pointing to the existing resource.

查看更多
成全新的幸福
4楼-- · 2019-01-05 07:34

I would go with 422 Unprocessable Entity, which is used when a request is invalid but the issue is not in syntax or authentication.

As an argument against other answers, to use any non-4xx error code would imply it's not a client error, and it obviously is. To use a non-4xx error code to represent a client error just makes no sense at all.

It seems that 409 Conflict is the most common answer here, but, according to the spec, that implies that the resource already exists and the new data you are applying to it is incompatible with its current state. If you are sending a POST request, with, for example, a username that is already taken, it's not actually conflicting with the target resource, as the target resource has not yet been posted to. It's an error specifically for version control, when there is a conflict between the version of the resource stored and the version of the resource requested. It's very useful for that purpose, for example when the client has cached an old version of the resource and sends a request based on that incorrect version which would no longer be conditionally valid. "In this case, the response representation would likely contain information useful for merging the differences based on the revision history." The request to create another user with that username is just unprocessable, having nothing to do with version control.

For the record, 422 is also the status code GitHub uses when you try to create a repository by a name already in use.

查看更多
ゆ 、 Hurt°
5楼-- · 2019-01-05 07:35

My feeling is 409 Conflict is the most appropriate, however, seldom seen in the wild of course:

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. The response body SHOULD include enough information for the user to recognize the source of the conflict. Ideally, the response entity would include enough information for the user or user agent to fix the problem; however, that might not be possible and is not required.

Conflicts are most likely to occur in response to a PUT request. For example, if versioning were being used and the entity being PUT included changes to a resource which conflict with those made by an earlier (third-party) request, the server might use the 409 response to indicate that it can't complete the request. In this case, the response entity would likely contain a list of the differences between the two versions in a format defined by the response Content-Type.

查看更多
在下西门庆
6楼-- · 2019-01-05 07:35

Why not a 202 Accepted? It's an OK request (200s), there were no client errors (400s), per se.

From 10 Status Code Definitions:

"202 Accepted. The request has been accepted for processing, but the processing has not been completed."

... because it didn't need to be completed, because it already existed. The client doesn't know it already existed, they didn't do anything wrong.

I'm leaning on throwing a 202, and returning similar content to what a GET /{resource}/{id} would have returned.

查看更多
成全新的幸福
7楼-- · 2019-01-05 07:36

What about 208 - http://httpstatusdogs.com/208-already-reported ? Is that a option?

In my opinion, if the only thing is a repeat resource no error should be raised. After all, there is no error neither on the client or server sides.

查看更多
登录 后发表回答