Create single and multiple resources using restful HTTP

23,490

Solution 1

In true REST, you should probably POST this in multiple separate calls. The reason is that each one will result in a new representation. How would you expect to get that back otherwise.

Each post should return the resultant resource location:

POST -> New Resource Location
POST -> New Resource Location
...

However, if you need a bulk, then create a bulk. Be dogmatic where possible, but if not, pragmatism gets the job done. If you get too hung up on dogmatism, then you never get anything done.

Here is a similar question

Here is one that suggests HTTP Pipelining to make this more efficient

Solution 2

There's nothing particularly wrong with having a bulk operation that you POST to, to activate (it'll be non-idempotent so POST is the right verb) but there are some caveats:

  • You're making multiple resources, so you need to respond with multiple URLs. This means you can't use the redirect pattern: you'll have to send a list of URLs back in some form.

  • You have a problem in that bulk operations are often not very discoverable. Discoverability is one of the most important things about RESTfulness, as it means that someone can come along and figure out how to write a client without lots of help from the server author.

  • Dealing with partial failures when you've got bulk operations remains problematic. It's a problem with any other paradigm too (I've watched people tie themselves in knots over this when working with extensions to SOAP) so it isn't a surprise, but unless you can guarantee that all the creations will work, you're going to have to work out what happens when you make one resource and fail to make the second. (Also, if the bulk request wanted a third one done, would you go on and try that?)

The simplest approach is just to support one create per request; that's a much easier pattern to get right and is better understood all round.

Solution 3

There's nothing wrong with creating multiple resources at once with POST (just don't try it with PUT). It's not "un-REST-ful", especially if you create a representation for the bulk operation itself. I suggest you create an index resource at the same time you create the individual resources, and return a "303 See Other" to it. That index representation would then contain links to all of the created resources (and possibly error information if any of them failed).

POST /categories/uploads/
[{"name": "Books"}, {"name": "Games"}]

    303 See Other
    Location: /categories/uploads/321/

(actually, now that I think about it, 201 might be better than 303)

GET /categories/uploads/321/

    200 OK
    Content-Type: application/json

    [{"name": "Books", "link": "/categories/Books/"},
     {"name": "Games", "error": "The 'Games' category already exists."}]

Solution 4

In your case I would also go the /bulk resource way. But the pattern I would suggest is the following and from my understanding the most natural: Work with the 202 Accepted status code.

The idea of a bulk request is that the server should not be forced to answer immediately as this would mean client needs to wait until it's bulk request completed.

Here is the pattern:

POST /bulk [{"name": "Books"}, {"name": "Games"}]
202 Accepted | Location: /bulk/processing/status/resourceId

GET /bulk/processing/status/resourceId
entry = "REST in peace" | completed | 0 errors | /categories/category/resourceId
entry = "Walking dead" | processing | 0 errors ->

So, the client POSTs the bulk information to the server. The server just accepts them with a 202 which gives no guarantee about the processing state at the time of response. But the server also provides the link to a status resource. Here the client can have a look on each of the created resources and the processing state. When finished the client can access the resource via the given link. Error cases can be identified by the client and erroneous data might be resend by a PUT on the completed resource.

Finally, a good advice I am usually following is: Whenever you hit a resource in your design that cannot be mapped on a HTTP feature it is probably because of a missing resource.

Solution 5

Actually this is still a hot topic till today, But simplify things I almost of the time say there is always a batter suited scenario for each practice. Eg: 1. If you are receiving the likes from a post you don't need the bulk as in case there is only one like per comment. 2. If you are receiving favorites comment the bulk can fit well by considering someone reviewing the comment he reads and check box all of his favorites and send it once.

Again this is based on my experience working with Restful API, and but currently for the sake of multi tasking and others things, me and my colleague we found our selves doing the bulk all the time in most MIS(Management Information System) we do. This is because modern days web app and mobile app that can do a lot of work and send the final results to the back-end, this way the back-end has little job to do as long as the data received don't violate the business logic.

Share:
23,490
wingy
Author by

wingy

Updated on November 06, 2020

Comments

  • wingy
    wingy over 3 years

    In my API server I have this route defined:

    POST /categories
    

    To create one category you do:

    POST /categories {"name": "Books"}
    

    I thought that if you want to create multiple categories, then you could do:

    POST /categories [{"name": "Books"}, {"name": "Games"}]
    

    I just wanna confirm that this is a good practice for Restful HTTP API.

    Or should one have a

    POST /bulk
    

    for allowing them to do whatever operations at once (Creating, Reading, Updating and Deleting)?

  • wingy
    wingy almost 12 years
    Why can't I return the created resources in the POST response directly?
  • fumanchu
    fumanchu almost 12 years
    Because that's RPC, not REST. The returned representations probably won't be cached; even if you happen to find a cache which does cache POST responses, it won't be cached at a URI which identifies the resource (it identifies resource creation, apparently).
  • fumanchu
    fumanchu almost 12 years
    Looks like Julian is looking over my shoulder ;) trac.tools.ietf.org/wg/httpbis/trac/ticket/347
  • s.m.
    s.m. almost 11 years
    +1 for "pragmatism gets the job done". I'm creating an API as well and, having to create thousands of resources, I think a bulk creation beats one POST per resource.
  • Markon
    Markon over 10 years
    @fumanchu: I don't completely agree. Read this: stackoverflow.com/a/1829913. Also, Restful Web Services says: "Entity-body: Should describe and link to the newly created resource. A representation of that resource is acceptable, if you use the Location header to tell the client where the resource actually lives."
  • GrumpyHat
    GrumpyHat over 4 years
    Also +1 for "If you get too hung up on dogmatism, then you never get anything done." - could not agree more.
  • shinzou
    shinzou over 2 years
    and basically ddos your system when you need bulk yes?