What's the correct way to view idempotency in terms of HTTP DELETE?

前端 未结 3 1517
轮回少年
轮回少年 2021-02-02 15:41

I have spent a lot of time recently reading the HTTP 1.1 specification and relating it to REST. I have found that there are two interpretations of the HTTP DELETE method in rega

相关标签:
3条回答
  • 2021-02-02 16:23

    Being idempotent does not mean that a request is not allowed to have side-effects (that's what the 'safe' property describes). It just mean that issuing the same request multiple times will not result in different or additional side-effects.

    In my opinion, the subsequent DELETE request should return an error - it's still idempotent because the state of the server is that same as if only one DELETE request were made. Then again returning the 200 OK status should be OK as well - I don't think being idempotent requires the returning of an error code for the subsequent DELETE requests - it's just that returning the error status seems to make more sense to me.

    0 讨论(0)
  • 2021-02-02 16:25

    Wikipedia defines Idempotence as an operation that:

    can be applied multiple times without changing the result beyond the initial application.

    Notice that they talk about the result of the operation. To me, this includes both the server state and the response code.

    The HTTP specification is a bit more vague on the matter. It defines it specifies that HTTP methods are Idempotent:

    if the intended effect of multiple identical requests is the same as for a single request.

    If you interpret effect as result in the Wikipedia definition then they mean the same. In any case, I question the practical benefit of telling clients that the resource as already been deleted.

    Final point: Idempotence is defined in terms of a single client. Once you start introducing concurrent requests by other clients, all bets are off. You are supposed to use conditional-update headers (such as If-Match-ETag) to deal with such cases.

    To reiterate: you should return the same return code, whether the resource just got deleted, was deleted by a previous request, or never existed at all.

    0 讨论(0)
  • 2021-02-02 16:29

    @MichaelBurr is correct about idempotency and side-effects.

    My opinion is that there are 2 states involved in a given REST request, the client's state and the server's state. REST is all about transferring these states between the server and the client, such that the client's state maps to a subset of the server's state, in other words, the subset stays consistent with the server. Because of that idempotency should mean that subsequent idempotent requests will not result in either state being different than it would be from only making the request once. With the first DELETE you would imagine that the server deletes the resource and lets the client know it can delete the resource as well (as the resource "doesn't exist anymore"). Now both states should be identical to before with minus the item that was deleted. For the client to do anything different when it tries to delete the item after it has already been deleted, then the state that is transfered from the server to the client must contain different information. The server can do things slightly differently with the information that the resource was already deleted, but once it responds with something different idempotency of the methods is essentially broken.

    For idempotent function:

    delete(client_state) -> client_state - {item}
    delete(delete(client_state)) -> client_state - {item}
    delete(client_state) = delete(delete(client_state))
    

    The best way to guarantee this idempotency is if the server's response is identical, that means the only way for the client's state to break the idempotency is for there to be non-determinacy or side effects in the client's handling of the response (which probably points to an incorrect implementation of handling the response).

    If there is an agreement between the client and server that the status codes exist outside of the representation of the state being transferred (REST), then it is possible to inform the client that the item "doesn't exists anymore" (as it would in the first request) with the extra comment that it had previously been deleted. What the client does with this information is unclear, but it shouldn't effect the resulting client state. But then the status code can't be used to communicate state, or rather if it does also communicate state in other situations (like maybe "you don't have permission to delete this item" or "item was not deleted"), then there's some introduced ambiguity or confusion. So, you at least need a pretty good reason for introducing more confusion into the communication if you want to say that DELETE is idempotent and still have the server's response depend on previous DELETE requests that are identical.

    HTTP requests involve remove methods, so the function might resemble

    delete(client_state) = send_delete(client_state) -> receive_delete(client_state) 
                                                     -> respond_to_delete(informative_state) 
                                                     -> handle_response(informative_state) 
                                                     -> client_state - {item} 
    
    0 讨论(0)
提交回复
热议问题