4

Suppose I have Task and TimePeriod. TimePeriod represents the time I have worked on the task using start_time and end_time fields.

I would like for Task to support Starting/Stopping the task. Start will create a new TimePeriod with the current time. Stop will add end_time to the last TimePeriod.

I was thinking the REST URL will be like this: PUT /tasks/1011?do=start PUT /tasks/1011?do=stop

or maybe PUT /tasks/1011/start PUT /tasks/1011/stop

What is the proper way to make this REST style?

mbdev
  • 6,343
  • 14
  • 46
  • 63

3 Answers3

2

I think Paul is real close, but it's important to note that pure REST requires an object/noun as a resource. Bearing in mind that I'm not a REST purest, I'm just throwing in my $0.02 as this pertains directly to REST. This is probably more technically correct:

Request: 
  POST /tasks/1011/timeperiod
Response: 201 Created response status with a Location header that points to 
  GET /tasks/1011/timeperiod/(identifier)

You should be able to then use /tasks/1011/timeperiod/(identifier) to update that. Stopping the time would probably involve a PUT, reseting (or rather deleting) the time would involve a DELETE. Your status page should come up anytime they actually land on GET /tasks/1011/timeperiod/(identifier).

Think key value pairs of object/id. Parameters in the GET shouldn't be necessary.

Christopher WJ Rueber
  • 2,141
  • 15
  • 22
  • 1
    Agreed on resources should be object/nouns. One way I've dealt with this is that the resource is a controller for an action, which is a tradeoff on the face many actions we want to take don't fit into the HTTP defined methods. This is just a naming change where you then have `/tasks/1011/start_controller`. One could also make an argument for a master controller where the action to preform is in the request body `POST /task/1011/controller action=start`, but I'd investigate the tradeoffs involved with this. – Paul DelRe Apr 06 '11 at 21:30
  • For me (personally), I could see doing it any of the ways suggested. I'm just trying to get to the heart of REST and the URI pattern problem that mbdev was asking about. I try to think of REST less as a set of laws and more as a set of strategies and apply them to problems using common sense. – Christopher WJ Rueber Apr 06 '11 at 22:10
  • Using this strategy is correct when it comes to REST however it's complex to implement on the client side. Since Stopping a task would require to place the current date using PUT with javascript. While an action can process this in server side which is easier. – mbdev Apr 12 '11 at 12:49
1

You want to conform to HTTP method definitions as much as possible when using REST to take advantage of the uniform interface. Using this rule, you wouldn't want to use PUT or a query string to pass an action. PUT wouldn't fit because it is to be used to replace a resource.

POST would be the method you'd want to use. POST /tasks/1011/start with preferably a response code 303 to redirect them to a status page (if that's needed for your use cases) or code 400 if starting failed. Similar for stopping a task.

I highly recommend RESTful Web Services Cookbook as I'm using that as a guide to this answer and it covers other common REST questions.

Paul DelRe
  • 4,003
  • 1
  • 24
  • 26
  • POST is used to create a resource and in this case the Task already exists. So PUT might be better to indicate the status changing to started/stopped – mbdev Apr 06 '11 at 20:52
  • 1
    Correct that POST is typically used to create a resource where you want the server to control where that new resource is to be located, but it's definition is broad enough to be used for other purposes. PUT has a concept of being idempotent which boils down to requesting the same resource multiple times should have the same effect, which in this case it doesn't sound is what you want. POST, on the other hand, is not idempotent. – Paul DelRe Apr 06 '11 at 21:23
1

Here is one alternative. Retrieve the task like this,

GET /task/1011

Then to start the task, POST it like this,

POST /ActiveTasks  

and to end the task,

POST /InactiveTasks   

In reality it doesn't matter what the URIs look like if you use the following representation for a task resource:

<Task>
  <Description>Do some stuff</Description>
  <Status>Active</Status>
  <Link rel="end" Method="POST" href="/InactiveTasks"/>
</Task>

or

<Task>
  <Description>Do some stuff</Description>
  <Status>InActive</Status>
  <Link rel="start" Method="POST" href="/ActiveTasks"/>
</Task>

Note that only one of the links will be available at any one time, depending on whether the task is currently active

Darrel Miller
  • 139,164
  • 32
  • 194
  • 243
  • I prefer this method unless I see an easier one. This solution will apply to more scenarios as well. For example now I have a project where I have to "confirm" an update operation on an item. We will be implementing it by sending with the item a Confirm URL to PUT on. – mbdev Apr 12 '11 at 12:50