title: exposing operations on resources RESTfully - overloaded POST vs. PUT vs. controller resources
body: <p>Say you've got a Person resource, and part of its representation includes a Location value which can have values like "at home", "at school" and "at work".  How would you RESTfully expose activities like  "go home", "go to work", "go to school", etc?  For the sake of discussion, let's stipulate that these activities take time, so they are executed asynchronously, and there are various ways in which they could fail (no means of transportation available, transportation breakdown during travel, other act of God, etc.).  In addition, the Person resource has other attributes and associated operations that affect those attributes (e.g. attribute=energy-level, operations=eat/sleep/excercise).</p>
  
  <p><strong>Option 1</strong>: Overload POST on the Person resource, providing an input parameter indicating what you want the person to do (e.g. action=go-to-school).  Return a 202 from the POST and expose activity-in-progress status attributes within the Person's representation that the client can GET to observe progress and success/failure.</p>
  
  <p><em>Benefits:</em> keeps it simple.</p>
  
  <p><em>Drawbacks:</em> amounts to tunneling.  The action taking place is buried in the payload instead of being visible in the URI, verb, headers, etc.  The POST verb on this resource doesn't have a single semantic meaning.</p>
  
  <p><strong>Option 2</strong>: Use PUT to set the Person's location to the state you'd like them to have.  Return a 202 from the PUT and expose activity-in-progress attributes for status polling via GET.</p>
  
  <p><em>Benefits</em>: Not sure I see any.</p>
  
  <p><em>Drawbacks</em>: really, this is just tunneling with another verb.  Also, it doesn't work in some cases (both sleeping and eating increase energy-level, so PUTting the energy-level to a higher value is ambiguous in terms of what action you want the resource to perform).</p>
  
  <p><strong>Option 3</strong>: expose a generic controller resource that operates on Person objects.  For example, create a PersonActivityManager resource that accepts POST requests with arguments that identify the target Person and requested action.  The POST could return a PersonActivity resource to represent the activity in progress, which the client could GET to monitor progress and success/failure.</p>
  
  <p><em>Benefits</em>: Seems a bit cleaner by separating the activity and its status from the Person resource.</p>
  
  <p><em>Drawbacks</em>: Now we've moved the tunneling to the PersonActivityManager resource.</p>
  
  <p><strong>Option 4</strong>:
  Establish separate controller resources for each supported action, e.g. a ToWorkTransporter resource that accepts POST requests with an argument (or URI element) that identifies the Person, plus a ToHomeTransporter, a ToSchoolTransporter, a MealServer, a Sleeper, and an Exerciser.  Each of these returns an appropriate task-monitoring resource (Commute, Meal, Slumber, Workout) from their POST method, which the client can monitor via GET.</p>
  
  <p><em>Benefits</em>: OK, we've finally eliminated tunneling.  Each POST means only one thing.</p>
  
  <p><em>Drawbacks</em>: Now were talking about a lot of resources (maybe we could combine the transporters into one Transporter that accepts a destination argument).  And some of them are pretty semantically contrived (a Sleeper?).  It may be more RESTful, but is it practical?</p>