Batch DELETE with REST
Lets say you have a blogging website where like any other site users can give insightful comments on the posts.
So far you are storing these comments in your database with Foreign key relationship to each articles or posts.
Entity Model looks like
Post Comment
{ {
id, -------Foreign Key-------> post_id,
author, id,
subject, user,
content comment
} }
Your blogging application got widely popular because of interesting articles being posted here and these articles started to receive hundreds of comments.
You feel happy to see your application receiving lot of attention but at the same time you are worried that it is consuming too much storage space. Moreover there are few irrelevant comments which does not make much sense. So you decided to show only first twenty relevant comments thread. To keep the quality of the discussion on the site high, blog authors can choose and delete irrelevant comments.
So purely from technical point of view how do we design an api to delete all selected comments.
One option is to have an API such as:
DELETE /comments/<comment_id>
Well, in this case we have to issue multiple requests to delete a set of comments. Not very efficient, not very performant from "bulk" point of view
How about using path params and a delimiter? Something like
DELETE /comments/1;2;3 or DELETE /comments/1+2+3?
Not a very good choice from standards point of view and it might trip intermediaries or proxies.
How? Look at following steps:
Step1: if DELETE /comments/1;2;3 is successful you might return 200 OK or 204 No Content. (See delete-with-rest-200-or-204 which one to use).
Step2: Proxy will see 200 OK and assume comment with an Id "1;2;3" is deleted from server and would issue a purge for /comments/1;2;3 in its own cache with the view to purge the response for the comment with Id "1;2;3" instead of purging
- /comments/1
- /comments/2
- /comments/3
It will not find comment with Id "1;2;3" and might cache 410 Gone or 404 Not found. Does not make much sense. Worse it might still continue to cache response for comments with Id 1,2 and 3. The behavior is undefined and surely is not something you would like to achieve
Ok so what are the options we have ?
Use POST as an all purpose method to tunnel these sorts of custom requests. This further can be achieved two ways: Synchronously and Asynchronously.
- POST /comments/bulk-delete with a JSON object in the POST body such as
{
"comments":[
{"comment":1},
{"comment":2}
]
}
If this is synchronous just response with 200 OK with status of deletion of each "comment." The advantage is this does not have to be "all or none". Deletion of few comments might fail and you are handling it gracefully, something like :
{
"comments":[
{
"id":1,
"status":"success"
},
{
"id":2,
"status":"failure"
}
]
}
This can also be achieved asynchronously. For that some extra work needed though. You need to have an endpoint where the status of deletion can be checked something like
GET /status/<id>
In that case you can return a 202 Accepted response with a location in header as
HTTP 1.1 202 Accepted
Location: /status/56785
Then to get the status you can simply issue a request GET /status/56785 and can return response based on the current state. To take our example if comment # 1 is successfully deleted , comment # 2 deletion failed and comment # 3 is still in pending a return could look like
{
"comments":[
{
"id":1,
"status":"success"
},
{
"id":2,
"status":"failure"
},
{
"id":3,
"status":"pending"
}
]
}
Also once the operation is completed either you can decide to keep this "status" data forever or may delete this after a specified time. Suppose you decide to delete that "status" after 24 hours after the entire operation is completed same get request GET /status/56785 should return 410 GONE.
Why 410 Gone and Not 404 Not found. Well both can be used but 410 indicated the resource was there and now gone. Will discuss these semantics some other time
http://techknowblogs.blogspot.in/2017/07/delete-with-rest-batch-delete.html
Hello, How would we avail the status data when we make a GET request at the endpoint /status/56785 ?
Hi, there, for this kind of situation, can we use the DELETE http method rather than the POST?