7

I want a server to be a producer of tasks for the client to process and be sent back. What is the proper HTTP method in RESTful approach to create and return a new resource?

This seems silly, but the natural way seems to be GET /task/, or more verbosely GET /new_task/. A task is being created and returned. But this doesn't seem right. POST also doesn't seem natural. Client does not want to POST any data. It rather requests it.

Use Case:

For example. I want to produce some tasks to perform, let's say some exercises. They need to be processed and sent back. My idea is to provide uri with GET method, to obtain a task. Save on the server that a task was obtained and save the time-out for this. Technically a task can be retrieved many times, and GET doesn't change it in any way, so it even seems idempotent. If a user POSTs answer to it the server will reply differently based on the saved time-stamp. However, I feels like at the same time I am also creating a new resource, i.e. (user; task; time-stamp) which semantically is "given-homework". What is the view in such case?

My ideas:

  1. GET /resource/ and create/generate and send it back. Let's say:

    {
      "self": "http://super-service/resource/<new_id>",
      "data" : "Ipsum Lorem... Your random stuff."
    }
    

Is this really idempotent? The "self" isn't really a mirror of GET this seems counter-intuitive for a GET request.

  1. Another way I can imagine is something like to POST a request for the resource to be created. E.g: POST /create_task/ which I don't think is a proper solution because it has a verb in URI. But one can workaround it let's say via: POST /task_request/, so now I am posting a request for a task, but it feels like fiddling with semantics to get it pretty. Still not sure if proper. The data in the response might be completely unrelated to the POST. Is that fine? Can the new data be a response (e.g. like from the case 1.)

I'd like to ask for motivation behind the proposed approach. So I can understand and learn the thinking process.

3 Answers 3

2

If the server creates tasks on its own, without a trigger from the user, and the user retrieves those tasks at some later time, then it would be proper to retrieve the complete list of tasks with

GET /tasks/

or, to get the tasks after you last checked

GET /tasks/?created_after=20160331

If, on the other hand, the server creates a new task in response to an action by the user, then

POST /tasks/

would be the right way to create a new task. There is nothing in REST that says that the content of the newly created task must come from the user. It is in fact very common that at least some fields are filled in by the server, depending on who has the knowledge to fill in those fields.
In your case, the large majority or even all the fields of a task would be filled in by the server.


If the tasks are related to a user, you can encode that also in the URL. For example

GET /users/{user_id}/tasks

to get all tasks for a user, or

GET /users/{user_id}/tasks/{task_id}

to get a single specified task and

POST /users/{user_id}/tasks

to create a task for a user.

1
  • +1 But, it'd be good to note how a client "claims" a task for itself. I'm assuming that's also a post. Maybe a POST to /tasks/{id} with {clientid:{id}} or something; boolean return value to indicate success?
    – svidgen
    Mar 31, 2016 at 13:49
0

Your hesitance is well-founded. I found it a little difficult to follow, but I believe what you are saying is you are considering an endpoint such that each time you request it it returns a new "fresh" result.

You are correct that using GET here would be bad to the point of possibly breaking things. You also had pretty good instincts with POST /task_request/. Something like that is what you want to do. The clients should POST to some URI like /task_request/ and it should return (on success) 201 Created with the Location header set to a URI, say example.com/task/1234. It can optionally return the content immediately as well, but it may be better to fetch it from the returned location (with a GET). The fact that the POST request may not have a body is not an issue. Once the user answers the exercise, it can be PUT to a URI, preferably one that was specified with the metadata for the task. (What URI that actually is doesn't really matter in that case.)

The benefits of this approach are we aren't abusing a HTTP verb in a way that could interact poorly with caching. You don't want someone requesting a new task to get a cached version of an old one, possibly the one they just finished. Even if you don't cache it, intermediate layers like content delivery networks may decide to cache it for you. Similarly, the client and intermediaries may decide to re-execute a GET request for a variety of reasons which may cause problems or at least create waste on your server. A POST won't be cached and won't be (blindly) re-executed. Meanwhile the created resource can then be re-fetched and cached as much as desired.

Generally speaking, using GET tells clients and intermediaries that the request can be cached and re-executed. Using PUT/DELETE tells clients and intermediaries that the request can be re-executed.

0

I think Bart's answer is noteworthy. But, if your server-side component is in the business of assigning tasks directly to particular clients, I'd propose one of these other options:

GET /client/me
GET /users/me
GET /somethingElseUniqueTo/me

Which would return a task or tasks property as part of client object. They can even be stubs:

{
  clientId: {id},
  tasks: [
    { taskId: {id} },
    { taskId: {id} }
  ],
  /* other stuff */
}

Which you then get the full details for at:

GET /tasks/{id}

And mark as being in-progress by updating a status field and POSTing to the same URL.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.