Idempotency of HTTP PUT and DELETE

So the HTTP specification says that HTTP PUT and DELETE should be idempotent. Meaning, multiple PUT requests to the same URL with the same body should not lead to additional side effects on the server. The same thing happens with multiple HTTP DELETEs if two or more DELETE requests are sent to the same URL, the second (or third, etc.) Requests should not return an error indicating that the resource has already been deleted.

However, what about PUT requests for a URI after DELETE? Should he return 404?

For example, consider that the following queries are executed in the following order:

  • POST / api / items - creates an item resource, returns HTTP 201 and URI / api / items / 6
  • PUT / api / items / 6 - updates the data associated with item # 6
  • PUT / api / items / 6 - has no side effects if the request body is similar to the previous PUT
  • DELETE / api / items / 6 - removes item # 6 and returns HTTP 202
  • DELETE / api / items / 6 - has no side effects, and also returns HTTP 202
  • GET / api / items / 6 - now it will return 404
  • PUT / api / items / 6 - WHAT SHOULD HAPPEN HERE? 404? 409? something else?

So, should PUT be compatible with get and return 404, or, as @CodeCaster suggests, would it be more appropriate?

+7
source share
2 answers

RFC 2616 , Section 9.6, PUT:

The main difference between POST and PUT requests is reflected in the different Request-URIs. The URI in the POST request identifies the resource that the attached organization will process. This resource can be a process of accepting data, a gateway to another protocol, or a separate entity that receives annotations. In contrast, the URI in a PUT request identifies the entity enclosed in the request - the user agent knows what the URI is, and the server SHOULD NOT try to apply the request to another resource.

and

If the resource cannot be created or modified using the Request-URI, you must give an appropriate error response that reflects the nature of the problem.

So, to determine the "suitable", you need to look at the 400-row, indicating the client error there. First I will eliminate the irrelevant:

  • 400 Bad request : the request could not be understood by the server due to incorrect syntax.
  • 401 Unauthorized . The request requires user authentication.
  • 402 Payment required . This code is reserved for future use.
  • 406 Not acceptable : the resource identified by the request [...] is not acceptable according to the accepted headers sent in the request.
  • 407 Proxy authentication required . This code [...] indicates that the client must first authenticate with a proxy.
  • 408 Request timeout . The client did not issue a request for the time when the server was ready to wait.
  • 411 Required Length : The server refuses to accept the request without a specific Content- Length.

So which ones can we use?

403 Forbidden

The server understood the request, but refuses to fulfill it. Authorization will not help, and the request MUST NOT be repeated.

This description is really well suited, although it is usually used in the context of permissions (as in: YOU CAN'T ...).

404 Not Found

The server did not find anything that matched the Request-URI. no indicates whether this condition is temporary or permanent. Status Code 410 (Gone) SHOULD be used if the server knows through some internally customizable mechanism that the old resource is permanently unavailable and has no forwarding address. This status code is usually used when the server does not want to indicate exactly why the request was rejected or when there is no other answer.

This too, especially the last line.

405 Method not allowed

The method specified in the query string is not allowed for the resource identified by the Request-URI. The response MUST include the Allow header containing a list of valid methods for the requested resource.

There are no valid methods to which we can answer, since we do not want any method to be executed on this resource at the moment, so we cannot return 405.

409 Conflict

Conflicts most often occur in response to a PUT request. For example, if version control was used and the PUT object included changes to a resource that contradicts a previously (third-party) request , the server may use 409 response to indicate that it cannot fulfill the request. In this case, the answer is likely to contain a list of differences between the two versions in the format defined by the Content-Type response.

But it is assumed that the URI already has a resource (how can there be a conflict with anything?).

410 gone

The requested resource is no longer available on the server, and no forwarding address is known. This condition is expected to be considered permanent. Clients with link editing capabilities SHOULD remove the Request-URI links after user approval. If the server does not know or is unable to determine whether the condition is constant, the 404 status code (not found) MUST be used instead.

That also makes sense.


I edited this post several times, it was adopted when it claimed that β€œuses 410 or 404”, but now I think 403 may also be applicable, since the RFC does not state that 403 should be a resolution (but it seems it is implemented on popular web servers). I think I deleted all the other 400 codes, but feel free to comment (before doing downvote).

+11
source

There is a vague, supposed premise in your question that the resource must exist for successful execution. This is a false assumption.

The relevant part of the specification (RFC2616) says:

the user agent knows what a URI is, and the server SHOULD NOT try to apply the request to another resource.

The specification does not say: "The object in the URI referenced must already exist in order for the PUT for this URI to succeed."


A simple example is a web store implemented through REST. GET returns the representation of an object at a given path, and DELETE deletes an element at a given path. It is easy. But POST and PUT are not much harder to understand. POST can do anything, but one use of POST creates an object in the container that the client specifies, and allows the server to return the URI of the newly created object in this container. PUT more limited; it gives the server a view for the object in the given URI. An object may or may not already exist. PUT not synonymous with REPLACE.

In my opinion, 409 or 410 is not true for PUT, unless the container itself - the thing you are trying to enter does not exist.

so:

 POST /container ==> returns 200 with `Location:/container/resource-12345` PUT /container/resource-98928 ==> returns 201 CREATED or 200 OK PUT /this-container-does-not-exist/resource-22828282 --> returns 400 

Of course, it is up to you whether you want your server to allow these PUT semantics. But there is nothing in the specification that says you should not allow clients to provide the URI of the resource that it is PUTting.

0
source

All Articles