0

I've been pondering this for a while now but can't wrap it around my head. Say I have a tasking system exposed through REST. Tasks have their own life cycle e.g.:

CREATED -> ACTIVE   ->  PROCESSING -> CLOSED
   |          |               |
   |          |-->ESCALATED-->|
   |
    --> DISMISSED

Now with POST I create the task by providing all the information in the body payload.

But now I only need to change the state of the task and maybe add a comment. So in all theory PUT is the way to go - it is updating a resource. But here is the thing:

PUT: /tasks/{taskId}?action=activate Seems legit URI however the action already has a request param that can be used to change the state of a resource - what about the PUT payload ? Is it intuitive for the user of this endpoint to send requests with 0 length message ?

UPDATE:

Sorry for my bad English as well. What I mean - is it a good practice to change the state of a resource by PUT request ONLY using URI parameter, without BODY (Content-Lenght:0) hence the URI: /tasks/32/?action=CLOSED to change "Task" state from PROCESSING to CLOSED.

If this is a bad practice approach - what approach is considered better practice ?

Xeperis
  • 1,449
  • 2
  • 25
  • 41
  • I'm not sure I got the point but, IMHO from a REST perspective you should PUT the resource with a body payload (like for the POST) and not by passing data via querystring; I assume that the querystring is only intended to GET a resource. – ilpaijin Apr 16 '15 at 17:23
  • and after 10 minutes of writing this I found this - http://stackoverflow.com/questions/7323958/are-put-and-post-requests-required-expected-to-have-a-request-body @ilpaijin - thanks for input, however what about the stack post above ? – Xeperis Apr 16 '15 at 17:25
  • I'm sorry for my bad english but I don't get your question "stack post above". – ilpaijin Apr 16 '15 at 17:31
  • @ilpaijin sorry, I meant stackoverflow post: http://stackoverflow.com/questions/7323958/are-put-and-post-requests-required-expected-to-have-a-request-body describes that POST for instance does not necessarily has to have a body. – Xeperis Apr 16 '15 at 17:48
  • @Xeperis that answer is out-of-date, based on RFC 2616, which is obsolete. POST and PUT require a body. In case of POST, you can have an empty body with a mimetype reflecting that, but PUT with an empty body would be semantically equivalent to DELETE. – Pedro Werneck Apr 16 '15 at 19:58

2 Answers2

5

Nope, you can't do that and call your application RESTful, for two reasons:

  1. URIs are atomic identifiers. You can't treat querystring parameters as method parameters or with the same semantics of the body payload. They are part of the identifier.

  2. PUT asks the server to replace the resource at the given URI with the submitted representation. You can't use PUT for partial updates like you are doing, and definitely you can't use PUT to apply querystring parameters in a partial update.

With that in mind, there are several options for doing what you want that can be considered best practices:

  1. You can PUT the whole representation, changing the status value you want to update. In other words, your clients will issue a GET, change the value in the document, and send everything back with PUT.

  2. You can PATCH a diff-document that applies the change only to the status value. Take a look at json-patch for an example of a data format that's compatible with the PATCH method.

  3. You can make a POST request to a dedicated endpoint that performs only the change you want, but you have to document how to use it. POST submits the payload to be processed by the target resource, so you can do anything you want with it.

Pedro Werneck
  • 40,902
  • 7
  • 64
  • 85
  • So suppose my client can only interact with resource in a number of ways - add a comment or change the state of the "task" resource, the best would be 2nd or 3rd option ? Because for the sake of argument lets say task can only be created by manager role and simple employee role user does not have all of the those powers just a subset. – Xeperis Apr 17 '15 at 15:20
  • Ideally, all your resources should support the 1st and 2nd option uniformly across your application, therefore you'd need to implement a POST only for an operation that isn't already standard. – Pedro Werneck Apr 17 '15 at 15:32
2

Yes it was an option based on old RFC but it has become obsolete (see rfc7231). Honestly, I feel quite unusual to think about the real usage of PUTting or POSTing a resource with an empty body and only with query parameters and values.

From what I know, a basic RESTful architecture consist of using HTTP verbs, call resources endpoints and create/update/delete that resources. (See comments from @PedroWerneck for further clarification).

This basically means that you use an HTTP verb (ie. PUT), calling a resource (tasks/abc) and send to that resource some data in order to modify it:

PUT /tasks/abc

title=abc&body=aabbccddeeff&status=changedToSomethingElse

that was created with

POST /tasks

title=abc&body=aabbcc&status=created 
ilpaijin
  • 3,645
  • 2
  • 23
  • 26
  • REST is protocol independent. It has nothing to do with HTTP. – Pedro Werneck Apr 16 '15 at 18:33
  • You're right about REST is not a protocol but I don't agree it has nothing to do with HTTP. I believe a REST architecture should communicate with HTTP verbs (also declared here http://en.wikipedia.org/wiki/Representational_state_transfer) – ilpaijin Apr 16 '15 at 21:09
  • REST can be implemented using any transport protocol.HTTP is the most common, but you are imagining a strong coupling where it doesn't really exists. – Pedro Werneck Apr 16 '15 at 21:11