7

I tried Googling and searching everywhere, but couldn't find a definitive authority on this topic. While being true to REST principles, how should I design the HTTP interface for:

  1. An ordered list (get, add, insert into position, reorder, remove)

  2. A set (get, add, remove)

  3. A hash-table (get, add, remove)

NOTE: These data structures are to contain references to existing resources with known ids

dadads
  • 201
  • 1
  • 8
  • 1
    1 year later: As it turns out, such philosophical ponderings have minimal impact on how well your application solves a problem. The real answer seems to be that it doesn't matter what you choose as long as you do not violate any specifications/requirements and cause any problems. – dadads Aug 13 '13 at 11:32

5 Answers5

10

That's how I would do it for an ordered list and hash table. I guess the methods would be the same for a set and a list:

Ordered list

Get item 123:

GET /list/123

Append an item to the list:

POST /list/

Insert new item into position 5:

POST /list/?position=5

Move item 123 to position 3:

PUT /list/123?position=3

Delete item 123:

DELETE /list/123

Delete item at position 3:

DELETE /list/?position=3

Of course, your API should update the indexes of all the elements when doing insertion and deletion.

Hash table

Get item "somekey":

GET /hashtable/somekey

Add item "somekey":

POST /hashtable/somekey

Remove item "somekey":

DELETE /hashtable/somekey
laurent
  • 88,262
  • 77
  • 290
  • 428
  • For hashtable I would suggest using PUT instead of POST, since you are specifying the URL of the object you are adding/creating. See https://stackoverflow.com/questions/630453/put-vs-post-in-rest – Asbjørn Jan 16 '19 at 08:59
2

@dadads

You can not define such interface directly.

An ordered list (get, add, insert into position, reorder, remove)

By excluding "insert into position" and "reorder" you can perfectly implement "get", "add" and "remove" for example:

  • You define your resource /service/users
  • You can use POST /service/users to add new user to the "users" collection
  • You can GET /service/users to retrieve users
  • You can GET /service/users/user-id to retrieve particular user
  • You can DELETE /service/users/user-id from users collection

This is a very rough example, though it outlines some ideas. In order to achieve "reorder" and "insert into position" you need to implement your own action semantics which you can include in your resource representation and let client know HOW to perform these operations. As a reference you can see this JSON PATCH specification proposal: https://www.rfc-editor.org/rfc/rfc6902 which tries to describe such operations.

It is not necessary to use already existing media format, you can define your own under your own namespace for example: application/vnd.your-company.format-name+json which describes these capabilities and also advertises this information to clients.

Community
  • 1
  • 1
ioseb
  • 16,625
  • 3
  • 33
  • 29
1

You should decouple the transport mechanism from the underlying application. I would consider designing the application correctly, then figure out how to access it via HTTP. This way you could easily add or change the transport mechanisms (SOAP, SCA, etc) without affecting the underlying application.

Once you have the application correctly designed, consider accessing it from the HTTP requests via something like an Adapter or Visitor pattern.

Brady
  • 10,207
  • 2
  • 20
  • 59
1

This is my idea for reordering.

There is a HTTP method called PATCH that is used to update fragments of a resource. Give your resource a new property called index, then make a call with PATCH method

PATCH /collection

[
  {
    "id: "original index 0"
    "index": 1
  }
  {
    "id: "original index 1"
    "index": 0
  }
]

Then your server back-end needs to figure out how to do this atomically. But interface-wise, I think this is the best way to stay true to RESTful.

Alternatively, there is a better solution, but it may not apply to everyone's case. Since ordering always depends some sort of criteria, it can even be as simple as insertion order. Let your collection url support an orderBy query string, and let this orderBy dictate on how the result gets ordered. Then during your reordering call from client, just update the resource's property used for the ordering criteria.

ming_codes
  • 2,870
  • 25
  • 24
0

I came to this question mostly looking for a RESTful way to reorder. I don't really like any of the answers, so here is what I think is most RESTful.

For reorder you could make the order a resource:

/list/order

Then you can do normal operations on it (for these examples assume a list with 5 items currently in it):

"items":" [
     {
         "id": "A",
         "name": "Monkey"
     },
     {
         "id": "B",
         "name": "Cow"
     },
     {
         "id": "C",
         "name": "Horse"
     },
     {
         "id": "D",
         "name": "Turkey"
     },
     {
         "id": "E",
         "name": "Tasmanian Devil"
     },
]

Note that "order" is not included in the resource response. It's not needed - the order is implicitly specified by the response order of the items.

GET /list/order

returns a list of item ids in their correct order

['A','B','C','D','E']

POST /list/order with payload ['D','B','C','A','E']

GET /list/order

returns a list of item ids in their correct order

['D','B','C','A','E']

Also obviously you would return the items in the list in the correct order when you do a GET on /list.

GET /list

returns a list of items in their correct order

"items":" [
     {
         "id": "D",
         "name": "Turkey"
     },
     {
         "id": "B",
         "name": "Cow"
     },
     {
         "id": "C",
         "name": "Horse"
     },
     {
         "id": "A",
         "name": "Monkey"
     },
     {
         "id": "E",
         "name": "Tasmanian Devil"
     },
]
richard
  • 12,263
  • 23
  • 95
  • 151
  • Wouldn't it be more restful to consider the collection of total orders so the resource becomes /lists/list{id}/total-orders/total-order-lt which would have the semantics of returning list{id} sorted using `lt` on its elements. /list/order is adding a verb into a RESTful api whilst considering the total_orders as elements of a sub-collection doesn't. – Jon Guiton Nov 26 '20 at 08:23