8

Say I have the following relational structure of data (for examples sake):

A `post` which is a child of a `category`

This data can be accessed via these API endpoints:

  • GET /category/1
  • GET /category/1/post/1
  • GET /category/1/post/2

I have now decided that I want to use my API to delete category 1 so I run DELETE /category/1.

However, category 1 has relational child post elements that can't exist without the category, would you expect this call to either fail and say you must first delete the child elements OR automatically recursively delete the child elements when you delete the category?

Dan
  • 11,914
  • 14
  • 49
  • 112
  • 1
    depends whether posts need to have at least one category. If they don't, they can exist on their own without a category so you don't need to delete them or their comments. If they need a category you'd need to delete all posts and comments in that category. A comment can't exist without a post so you'd delete all comments for a post if you deleted the post but whether a post can exist without a category is up to your domain model. – codebrane Jan 30 '18 at 11:14
  • For this example a comment belongs to one post and a post belongs to one category. The question is more about the RESTful approach of where to DELETE child items - through one call to the parent element, or to multiple calls to each child element before deleting the parent. – Dan Jan 30 '18 at 11:16
  • 1
    In what sense do you say it is recursive? Because the recursiveness is an implementation details and the client should not bother about it I feel. Since if you would take a basic CRUD implementation on a RDBMS, you'll most likely cascade you're deletes, so the success case will mostly be the expected behaviour in a general sense. But all this also depends on your business requirements as well. – Abhishek Nair Jan 30 '18 at 11:17
  • The question is - from a RESTful API perspective, should `DELETE /category/1` fail because child elements exist and it shouldn't be in charge of deleting them OR should it succeed and forcefully be in charge of deleting those items. – Dan Jan 30 '18 at 11:20
  • So it's an implementation issue. The server should implement the policy. If the policy states a post must be in a category and the client deletes the category, then I'd say the server should implement the policy, not the client. i.e. a single DELETE of the category should trigger the server to do everything needed to implement the policy, i.e. delete all posts/comments in that category. In theory. there may be other things to do such as email post owners when their post is deleted etc. The client should be aware of the policy, not how the policy is implemented. – codebrane Jan 30 '18 at 11:21
  • 1
    I don't really understand what is your issue. But, if you are able to call `GET /category/1` (get all) you should also be able to call `DELETE /category/1` (delete all). – alex Mar 05 '18 at 19:54
  • 1
    What does REST have to do with api-design? REST doesn't care how the URIs are designed. This also includes that URIs do not have to follow a logical structure. A client will use link relation names and media-type to deduct whether to invoke that URI or not. The relation between entities should therefore be given via additional URIs returned instead of relying on a logical URI structure. Mapping your database model 1:1 to your REST API is thus bad design in general – Roman Vottner Mar 07 '18 at 07:54
  • The point is - if you have a relational database with a REST api - should a delete call succeed or fail if the element you're trying to delete has child elements. I think that's a valid question in API design and stating that it's a RESTful API is likely necessary for the outcome of the question. Question edited to be simpler to understand. – Dan Mar 07 '18 at 12:30
  • 1
    Your question does not make any sense since the implementation details are up to you and your specific use case. You can either drop all related records... or throw 400 if parent record has child elements. Still it's only up to you, REST does not impose anything. – Mike Doe Mar 12 '18 at 11:29
  • 1
    I would design it in a way, that `DELETE` is only allowed on a category if all related posts were deleted in before. That means to send an appropriate `ALLOW` header depending on the status of the category. For the deletion of all posts within a category I would create a more descriptive endpoint like `DELETE posts?filter=category:1`. See my answer for more details https://stackoverflow.com/a/49118002/1485527 – jschnasse Mar 16 '18 at 07:42

4 Answers4

3

IMO this is more of a design decision and their really is no wrong way to do it. So it all depends on the requirements.

If you decide that deleting a category deletes all the child post elements, then you can do that in multiple way (ordered by my preference).

  • Control that cascading deletes in the database.
  • Add code in the DAL layer so that when a category is called, it deletes all the post under the category.

If you decide to not do the "cascade" delete for the child post, then your only option is to return an appropriate error message stating why the category cannot be deleted.

If you want you can make it more clear what the call to the web service does by doing something like this.

DELETE /category/1?includePost=true --> Deletes category #1 & all post under it.

DELETE /category/1 --> Delete category #1 or returns error if it can't delete it.

smehaffie
  • 379
  • 1
  • 10
2

I would say it should succeed when you DELETE category.

Let's say, it fails - then you would need GET all posts and comments then iterate over them with DELETE - what's the point?

Also, I would use plural nouns for resource naming like:

GET /categories/1/posts

When getting all posts it would look more consistent.

However, it's up to you how to implement it, with or without cascading - look what better suits your needs.

Justinas Jakavonis
  • 8,220
  • 10
  • 69
  • 114
1

1. Naming

  • I would use the plural form, /categories, /posts, /comments
  • in my opinion, /categories is not a good name for something that allows one to recursively delete a large number of entities from your database. I would use something like /sections, /areas or /partitions for that purpose.
  • Instead of DELETE /categories you could offer something like
  • DELETE /posts?filter=category:1

2. Routing

I would consider to use a more flattened structure for the http routes, and create independent endpoints for each entity.

Provide CR (create,read) for

GET,POST /categories
GET,POST /posts
GET,POST /comments 

Then provide RUD (read,update,delete) for the single entities

GET,PUT,DELETE /categories/1
GET,PUT,DELETE /posts/1
GET,PUT,DELETE /comments/4

In my opinion, this makes usage more intuitive and does not imply some kind of hierarchy or a certain behavior. Now define DELETE on each entity like appropriate.

3. Implementation

Example

  • DELETE /posts?filter=category:1

    Delete all posts belonging to category with id 1

  • DELETE /categories/1

    • if /categories/1 is 'empty'

      Just delete one entity of type category.

    • if /categories/1 is 'not empty'

      return a HTTP 405 Method Not Allowed and ask the user to run a DELETE /posts?filter=category:1 to empty /categories/1 first.

  • OPTIONS categories/1
    • if categories/1 is 'empty'

      set ALLOW to GET,...,DELETE

    • if categories/1 is 'not empty'

      set ALLOW to GET,... (do not allow DELETE)

  • DELETE /posts/1

    Delete the post and all comments referencing it OR use the same pattern as for DELETE categories/1

  • DELETE /comments/1

    Delete just the comment.

4. Find further information

Which HTTP status code to return when the DELETE operation is not allowed for particular reason

Community
  • 1
  • 1
jschnasse
  • 8,526
  • 6
  • 32
  • 72
-1

You can able to perform these actions in Rest

"methods": [ "GET", "POST", "PUT", "PATCH", "DELETE" ],

I can able to do this thing by DELETE /categories/1/post so naming should be followed.

Sheel
  • 847
  • 2
  • 8
  • 20
  • Are you saying you'd expect DELETE /categories/1/post to delete all posts in that category, so that the OP could then delete the category? That's arguably a similar cascade to the original delete. – Rup Mar 14 '18 at 00:37