Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What are the options for handling flags and attributes in a REST API?

Tags:

rest

http

api

Let's say you have a complex resource in a REST API. You have several one-to-many flags and attributes on this resource (i.e., a user may have given the resource a rating of 1 to 5 or the user may have 'liked' the resource or marked it as spam or ignored it or caused some other state to be set).

Some suggestions have been made on the best way to represent this in a resource-centric architecture, but so far none of them have really made me happy. So let's crowd-source this; which variants do you find easiest to understand? Which variants haven't we thought of? Assume an OAuth-based API and everything here is done in the context of the currently authorized user.

  • Boolean Flags

    • Variant 1:

      GET /resource/{id}/muted
      POST /resource/{id}/muted BODY:true
      POST /resource/{id}/muted BODY:false
      
    • Variant 2:

      GET /resource/{id}/muted
      PUT /resource/{id}/muted BODY:true
      DELETE /resource/{id}/muted
      
    • Variant 3:

      GET /resource/{id}/attributes
      POST /resource/{id}/attributes BODY:muted=true
      POST /resource/{id}/attributes BODY:muted=false
      
    • Variant 4:

      GET /resource/{id}/muted
      POST /resource/{id}/mute
      POST /resource/{id}/unmute
      
  • Attributes

    • Variant 1

      GET /resource/{id}/rating
      POST /resource/{id}/rating BODY:4
      
    • Variant 2:

      GET /resource/{id}/rating
      PUT /resource/{id}/rating BODY:4
      DELETE /resource/{id}/rating
      
    • Variant 3:

      GET /resource/{id}/attributes
      POST /resource/{id}/attributes BODY:rating=4
      POST /resource/{id}/attributes BODY:rating=
      

Thoughts? Suggestions? How have other APIs handled this? How have you handled it? Have you found that design issues like this have had significant effects on developer happiness or the ease-of-use of your APIs?

like image 471
Bob Aman Avatar asked Nov 02 '10 00:11

Bob Aman


1 Answers

From Roy's dissertation:

a uniform interface degrades efficiency, since information is transferred in a standardized form rather than one which is specific to an application's needs. The REST interface is designed to be efficient for large-grain hypermedia data transfer

So you need a variant 5 which works for both flags and other attributes:

GET /resource/{id}/  BODY:{muted: false, like: false, rating: 2, ignored: true}
POST /resource/{id}/ BODY:{muted: true, like: false, rating: 2, ignored: true}
POST /resource/{id}/ BODY:{muted: false, like: false, rating: 2, ignored: true}

One big reason is that most of a RESTful HTTP application's efficiency comes from caching, and that works best when its artifacts are at as large a grain as possible, and when its data is reachable at as few identifiers as possible. If you expose the 'muted' flag at both /resource/{id}/ and /resource/{id}/muted, then you have a cache invalidation problem. If you expose it only at /resource/{id}/, then you don't.

If you are designing an application that aims for efficiency via small payloads, then you cannot benefit from large grain caching, and the REST architectural style is not appropriate for your app. HTTP probably isn't either, but I can understand how someone might be stuck with that in today's market.

like image 137
fumanchu Avatar answered Oct 31 '22 21:10

fumanchu