tags:

views:

77

answers:

4

I am trying to design a "collection of items" resource. I need to support the following operations:

  1. Create the collection
  2. Remove the collection
  3. Add a single item to the collection
  4. Add multiple items to the collection
  5. Remove a single item from the collection
  6. Remove multiple items from the collection

This is as far as I have gone:

Create collection:

==>
POST /service
Host: www.myserver.com
Content-Type: application/xml
<collection name="items">
 <item href="item1"/>
 <item href="item2"/>
 <item href="item3"/>
</collection>

<==
201 Created
Location: http://myserver.com/service/items
Content-Type: application/xml
...

Remove collection:

==>
DELETE /service/items

<==
200 OK

Removing a single item from the collection:

==>
DELETE /service/items/item1
<==
200 OK

However, I am finding supporting the other operations a bit tricky i.e. what methods can I use to:

  • Add single or multiple items to the collection. (PUT doesn't seem to be right here as per HTTP 1.1 RFC
  • Remove multiple items from the collection in one transaction. (DELETE doesn't seem to right here either)
+2  A: 

You would be better off using a non-positional identifier such as a UUID for collection items, to avoid problems such as the url of an item changing when you delete an item that precedes it. (Of course, you can still use itemN or just N, as long as the number stays attached to the same item at all times, leaving gaps after deletions, but a UUID is less confusing.)

The collection has the url /service/items. Each item has the url /service/items/<id>.

  1. Creating items and collections is a POST on the parent of the resource.
    1. You could use a PUT if the client has the right and ability to generate the name or id of the resource.
  2. Removing items and collections is a DELETE on the resource itself.
  3. Adding multiple items is either multiple POST or a multi-item POST on the parent (the collection).
  4. Removing multiple items is a DELETE on each resource. I would discourage multi-item DELETE for two reasons:
    1. Bulk deletion is a dangerous operation (for which reason, I would also discourage DELETE on a non-empty collection).
    2. The only meaningful target of the operation is the parent collection, thus making bulk DELETE asymmetric with respect to single-item DELETE.

If you really need bulk deletion capability, provide it through a different, clearly marked API, such as PURGE /service/items.

Marcelo Cantos
A: 

to add items to the collection, you POST them to the collection's URL (http://myserver.com/service/items). in your case, you already have a 'multiple items' representation in XML, just POST that.

I don't know a simple way to remove multiple items on a single operation... may you could PUT to the collection's item with a list of id's to retain. the idea being that PUT updates the container, so what's not there is removed. and, i think it's not useful to provide the whole data you want to keep, just the references of the items.

Javier
A: 

What's wrong with PUT to create an element? You cited the HTTP RFC, but the HTTP RFC doesn't preclude the use of PUT to create an element in your collection, as far as I know. If I've missed something, please make a specific citation, with an excerpt.

The key difference between PUT and POST to create elements:
PUT should be an idempotent operation; POST is not.

For deleting multiple elements in a single transaction, you can send DELETE to a URL that specifies a range (/service/items/13-20, or you can send DELETE to /service/items and use the HTTP Range header (See RFC2616 sec. 14.35.2). Normally the range header is contrued to imply a byte range, and is used on a GET request, but it's up to your resource to infer the meaning of RANGE on a DELETE.

Cheeso
The RFC suggests that data sent in a PUT request should be interpreted independently from the data already present at the URI. i.e. the client would have to send the complete payload again which shall be replaced with the existing data at the URI.e.g. if the collection contains item1,item2, item3 and we need to add another item (item4), then the payload of the PUT request should contain not just item4 but item1,item2,item3,item4 which in case of large number of items in the collection is inefficient.
Suresh Kumar
Yes, for PUT you must specify the full content for the current resource. But **NO**, you need not specify the content for other resources. If you invoke PUT on /service/items/4, then you need not specify the content for item2 or item3.
Cheeso
A: 

Why not use the AtomPub spec and adhere to the decisions written there? This way new clients could easily consume your data (using GData libraries..simple) and things like paged data feeds and the symantics of GET/POST/PUT/DELETE are solidly defined. Just my $.02.

Gandalf