标签云

微信群

扫码加入我们

WeChat QR Code

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


As of June 2016 FB blatantly sets 200 on registration when email exists

2019年06月26日06分38秒

Github API returns 422 when trying to create a resource (team/repo) with a name that is already in use

2019年06月26日06分38秒

It depends if you consider the existence of the object an error or not. If you process the append, 200 or 204 are the most appropriate response codes.

2019年06月26日06分38秒

why not go for 400 Bad Request? For me this looks a bit like a validation error (you are providing wrong payload with illegal id).

2019年06月26日06分38秒

400 => "The request could not be understood by the server due to malformed syntax". And the server understands perfectly, but is unable to comply due to a conflict. There is nothing wrong with the request & syntax, only a data problem. A 400 would instantly make me believe the whole mechanism I'm using is flawed, instead of just the data.

2019年06月26日06分38秒

Wrikken That is no longer correct. HTTP 400 was changed in RFC 7231 to mean "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)." I'm not saying 400 is correct usage in this case but it could be correct with the new definition of 400.

2019年06月26日06分38秒

javajavajavajavajava: still, duplicate data is not a 'client error' in my mind, but that's in the eye of the beholder of course.

2019年06月26日06分38秒

I return HTTP 409 with a Location header pointing to the existing/conflicting resource.

2019年06月26日06分38秒

In my opinion, this might a well be the accepted answer. Though "MAY" indicates a completely optional item, it is the only response code suggested by the official RFC 7231 documentation.

2019年06月25日06分38秒

This is the most RESTful answer.

2019年06月26日06分38秒

I think context is important. For example: returning a 303 implies a redirection to the found resource is needed. That might make sense in a server to server call, but if you were running through a user registration process, it would make no sense at all.

2019年06月26日06分38秒

Sorry, I'm downvoting this. The HTTP 300s are about redirecting, and redirecting to another object which probably has different properties would be very misleading.

2019年06月26日06分38秒

You don't have to be sorry. However, if the representation is equivalent to an existing resource, how can it have different properties? And even if it would have, how would a redirect be misleading? The OP says: I'm not sure what to do in case the object is already there. It is in fact the 'same' object. Why would a redirect be misleading? You're talking about another object which in the mind of the OP clearly isn't.

2019年06月26日06分38秒

This is an interesting thought, and prompted me to finally read the WebDAV RFC.However, I think the meaning of 422 is that the request and the included entity were syntactically correct but semantically didn't make sense.

2019年06月26日06分38秒

Malformed JSON is not a syntactically correct entity, so a 422 strikes me as odd...

2019年06月26日06分38秒

I would not go with this. From the same URL referenced in the answer: "For example, this error condition may occur if an XML request body contains well-formed (i.e., syntactically correct), but semantically erroneous, XML instructions." This is the real meaning of an unprocessable entity, unlike the case when you send completely valid request entity with valid syntax AND semantics, but the only problem is that it conflicts with an existing entity. Actually, if the semantics of the request entity were not valid, there should not be a similar, existing entity at all.

2019年06月26日06分38秒

Adding to Tamer comment, if the second request came first, then it would succeed, which will not possible if that was semantically correct. Hence in correct semantics wouldn't apply here.

2019年06月26日06分38秒

Tamer Why so? The command "Please create object xy" is syntactically correct. It is semantically correct only if it is possible to create object xy. If object xy already exists, it can no longer be created, hence this is a semantic error.

2019年06月26日06分38秒

I think 403 Forbidden implies that, even though the user is authenticated, he is not authorized to execute the requested action. I would not use it for validation errors. Example: Not logged in, I attempt to delete something. Server sends me 401 Unauthorized (which is just badly named, should be 401 Unauthenticated). I log in and try again. This time the server checks my permissions, sees i'm not allowed and returns 403 Forbidden. Also see this question.

2019年06月26日06分38秒

Hm... true. The thought here was jumping right to telling the user that their authorizations make the resource immutable in the OP's use-case - it already exists, you have no permission to do anything to resolve the conflict, don't try creating the resource again.

2019年06月26日06分38秒

According to the spec, it is implied that error 409 cannot be returned by a POST request (when used correctly), as it states that it should be returned when it conflicts with the target resource. Since the target resource has not yet been posted to, it cannot possibly conflict, and thus to reply with 409 Conflict does not make any sense.

2019年06月26日06分38秒

I would not infer that a 409 error cannot be returned by a POST, in fact, I would infer the opposite because "Conflicts are most likely to occur in response to a PUT request." seems to indicate that other request methods can also use this code. Additionally, "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." (webdav.org/specs/rfc2616.html#status.409)

2019年06月26日06分38秒

3xx statuses are meant for redirection

2019年06月26日06分38秒

"The requested resource resides temporarily under a different URI." from w3.org/Protocols/rfc2616/rfc2616-sec10.html

2019年06月26日06分38秒

IMHO, "307 Temporary Redirect" is the real temporary redirect. "302" is ambiguous, but "FOUND!!" is the really desired message here. The best unambiguous compromise is "303 See Other" on the HTTP semantics. I would go with "303 See Other".

2019年06月26日06分38秒

3xx codes are not errors!

2019年06月26日06分38秒

DavidVartanian Thanks for the discussion. Updated the answer towards 409. The client is wrong to ask for impossible stuff, even if it does not know that it is impossible.

2019年06月26日06分38秒

What about an object that has a join table relation? Say we have account, product, and account_product as database tables. I want to add a product to an account, so I would want to post to /account/{id}/product with the product_id. If only one account-product relationship is allowed, what should I return?

2019年06月26日06分38秒

Forget the database tables. Let's say a product can only be related to an account... Then it's one to many relationship. So, POST /product/{id} with {'account':account_id}. If you have the max cardinality set to '1' (one to one relationship).... Why are they separated rest objects? An error of cardinality will be just a 400 err. Keep it simple. I hope I understood your question.

2019年06月26日06分38秒

I just posed this question also and for me the ID is not the technical ID on the database but the something like the company code. In this application a manager user can create companies and has to give them a code. This is the company ID for the user, despite the fact that the DB table also has a technical ID. So in my case I'll return a 409 if the same company code already exist.

2019年06月26日06分38秒

partkyle Stop using PKs as public IDs!!

2019年06月26日06分38秒

Some entities have unique constraints on them, not just the id. Like an account, you can't create an account if user doesn't provide username. And adding an account with no username is obviously impossible

2019年06月26日06分38秒

The request is not duplicating a resource, it is appending data to one. In my opinion, yours is the best answer of all.

2019年06月26日06分38秒

According to the spec, it is implied that error 409 cannot be returned by a POST request (when used correctly), as it states that it should be returned when it conflicts with the target resource. Since the target resource has not yet been posted to, it cannot possibly conflict, and thus to reply with 409 Conflict does not make any sense.

2019年06月26日06分38秒

Debatable imo. If you post to /users then the resource is the collection instead of the individual record /users/{id}

2019年06月26日06分38秒

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

2019年06月26日06分38秒

I do like your suggestion to use PUT though.

2019年06月26日06分38秒

This answer is wrong. 202 means that the server did not find a problem with the request, but chose to process the request after responding. It also means that it expects that the processing to be successful. In our case the server knows that the processing will fail, so 202 is the wrong response.

2019年06月26日06分38秒

An example of 202 would be a queue or subscription. In other words, the result of the request may not be available immediately if you were to query it right this moment.

2019年06月26日06分38秒

This would be appropriate if the server were still processing the request. 200 or 204 would be more common. Since the OP is making an append request, existence of the object is an expected condition and not an error.

2019年06月26日06分38秒

There is no sense in saying to the client that the request was accepted because you already knows that it wasn't!

2019年06月26日06分38秒

Patch is like PUT but not a complete replacement. It's used to modify a piece of the resource like adding, removing, or modifying a single element of the resource instead of replacing it as a whole.

2019年06月26日06分38秒

This is no option due you want to append a certain item which id is already existing. So you try to add something but this is already there. A OK would be only apply if the data set was grown. Append Something -> Ok I appended nothing. Does not fit, I guess.

2019年06月26日06分38秒

A 2xx error code cannot indicate an error.

2019年06月26日06分38秒

As I said, I don't thing this is a error.But I see the point of martin

2019年06月26日06分38秒

If the resource is not successfully created, then there is by definition an error.

2019年06月26日06分38秒

POST is also used for appending data. This is by definition, not an error.

2019年06月26日06分38秒

My understanding: "status code indicates that the target resource has more than one representation ... information about the alternatives is being provided so that the user (or user agent) can select a preferred representation by redirecting its request to one or more of those identifiers" We are explicitly trying to prevent more than one representation. There are no options. There are no alternatives for the client to choose from. The client should resubmit with a different id. With that said, one should also consider whether unique ids should be generated in the client vs. server.

2019年06月26日06分38秒

Semantically, the client is saying "Create this" and the server is responding by saying "Go here instead". The conversation doesn't make any sense. It's almost as if the server is telling the client to "post to this location instead". 300s are more a more appropriate response to a GET request or a POST in the case where the server is responding with "Ok I created it and it's over here"..

2019年06月26日06分38秒

A 3xx error code cannot indicate an error.

2019年06月26日06分38秒