Is HTTP 404 an appropriate response for a PUT oper

2020-03-01 03:00发布

问题:


Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.

Closed 2 years ago.

Imagine a REST webservice where you are adding items to some type of container. For example, lets say we could add a attendee #789 to a event #456 like this:

PUT http://..../api/v1/events/456/attendees/789

If either event #456 or attendee #789 do not exist, is it correct to return an HTTP 404 (along with a detailed error payload explaining what the problem was, e.g. { "error" : { "message" : "Event 456 does not exist" , "code" : "404" } }?

Similarly, what if I am creating something new which refers to another object, but the other object does not exist? For example, imagine I am creating an event at Location #123

PUT http://..../api/v1/event
{ "location": 123, "name": "Party", "date": "2012-05-23", ...etc... }

If Location #123 does not exist, is it also correct to return 404 (along with detail in response)? If not, what would be appropriate -- just a 400?

According to the HTTP 1.1 spec http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html

9.6 PUT ... If the resource could not be created or modified with the Request-URI, an appropriate error response SHOULD be given that reflects the nature of the problem

So that would seem to be a good vote for responding with 404. However for some reason I can't quite put my finger on, responding to PUT (or POST) with a 404 seems odd to me... Perhaps it's because 404 means that the resource cannot be found, but in this case our resource is actually a linkage between two other resources, and it's one of those two resources that can't be found.

Don't get too worried about my exact examples here -- they are made up to illustrate the point. The main question is: is 404 an appropriate response to a PUT operation that fails because a linked resource is not found?

It would be excellent if you can point to references -- I'm having a hard time finding any that get into this level of detail and are also sufficiently credible. Especially as regards treatment of resource relationships in REST API design.

Updated thinking I'm thinking that possibly the first example should return 404, the second should not. The reasoning being that in the first case the resource we're adding uses event 456 and attendee 789 as it's composite primary key; the second case location is only a foreign key. In the second case an error should be returned, but not a 404 -- possibly a 412 Precondition Failed or maybe just a 400 Bad Request. Thoughts?

回答1:

There are a number of 4xx HTTP status codes. The most likely are either 404 or 409:

404 Not Found

The server has not found anything matching the effective 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.

409 Conflict

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 representation 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 representation 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 representation would likely contain a list of the differences between the two versions.

Either of those would be suitable, but I think I'd go for 409. 404 is used for URI not found but 409 indicates the current state of the resource doesn't allow the operation requested. In your case, the request can't be satisfied because something is amiss which doesn't allow it.