How to allow a user to create/update bulk data and be restful? - rest

I'm creating a web API and I have a scenario where users will want to load a bunch of data in bulk, which would then be loaded into the database as multiple separate entries. This data could be brand new and thus created, or data may already exist and thus be updated. The definitions for POST and PUT seem to expect to work on only a single piece of data at a time, and the created status code reflects that in providing a location.
I already have methods that allow for a single piece of data to be created or updated. Should I write additional methods to facilitate the creation and updating of this bulk data or should I expect the user to make individual calls (perhaps hundreds of thousands of times) to load their data? What should I be returning as far as status codes and other data is concerned? Which request verbs should define these bulk calls?

The RESTful way to create multiple items inside a collection, is to use PUT on the whole collection.
This way you are making a request to replace the whole collection, so you need to pass both old and new items, but the new ones will be created by the server.
Suppose you had only one item in the /items collection called "old item". Here you request to update a collection so that it has two new items.
PUT /items
[{ Name: "old item"}, { Name: "new item 1"}, { Name: "new item 1"}]
You don't need to return any content inside a successful PUT response because success in this case means that the exact state you requested was applied. So it leaves status code 204.
And since you are updating a whole collection resource, you don't return 201 regardless of whether new items were created or not.

Related

Upsert (update or insert) of resources with generated URIs in REST?

My data access layer supports the upsert operations (Spring Data's CrudRepository.save()), when the id field is not set a new record is inserted and when the id field is set it is updated.
I am wondering how to justify the additional effort required to create two separate REST methods (both on the backend and the frontend side):
POST /users, for creating a new user (and generating the URI of the newly created resource)
PUT /users/{id}, for updating the existing users
over creating just one REST method:
POST /users
Are there any benefits of having two seperate methods other than being more RESTful?
It's more clearer to using different resources for different actions.
By REST ideology - PUT Idempotent method and POST not Idempotent. So each POST request should return new item in response, but PUT should return the same item in response.
I think it's a good when behavior is expected.
But if you write documentation for your api, you can using one resource for both actions (but I would choose the first option).
The data access layer supporting upsert does not mean that the REST API should support it, too. I would not overload POST /users with two meanings. Stick to two different resources.
Edit:
POST /users has the general meaning of 'add a new instance to the resource collection'. I see no way to extend this to '... or update existing instance if an ID is given'. /users is the collection resource, not a single resource you want to manipulate. Doing a POST to a collection resource should manipulate the collection, not a single existing resource.

simple model when requesting collection and extended model when requesting resource - how

I have the following URI: /articles/:id, where article is a resource on web-service and have associated model/class. Now I need to return only partial data for each resource (to save bandwidth and make for speed) when collection is requested, but when a single item is requested from collection I need to send full data. My question is should I use two models/classes for the same resource on the server and initiate different one depending on collection or single resource is requested? Or maybe there is should be only one model/class but not all fields should be filled with data when a collection is requested? Or maybe there is another approach?
I suggest using the approach suggested here with a fields query parameter.
If the API is going to be open to everyone to use and client usage is going to be unpredictable, then by default you probably need to limit the fields that you return. Just make sure you document in some way all the possible fields that could be used, in case a client actually needs them.
If the API is going to be consumed only by an app or apps you made, then by default you could return all of the fields and then your app can pass that fields parameter to speed things up.

Which way should I create a list of objects when sending POST request

When I creating same type objects and save them into database, should I send a list of that objects in one request or should I send individually for each one?
For example, I would like to create a todo list, I can create multiple todos, then click save to send a list of todos, or when I finish editing one todo, I save it directly.
The first way can save request numbers, only one request needed to create many objects. But is the first way RESTful? All infomation about create in REST is creating a single object, but will there be poblems if increasing requests numbers?
----Edit
Thank you guys answering me.
For a more spicific usecase, I am using Django Rest Framework. I created a Todo model and a corresponding serializer. I am wondering, how could I create a list of Todos? I tried to send a list of Todos to serializer, and expecting serializer can automatically loop through it as same as getting a list of instance. But that doesn't work. I know I may be able to create a loop to call create method everytime. But is there a better way to do it?
There is nothing in REST that tells you what kind of payload you are allowed to use. You can POST/PUT whatever you want - one entity representation or many representations, in lists, dictionaries, XML, URL-encoded key/values or JSON, what ever suits your use case best.
In your case you might even want to send a delta/diff list of changes on the client: Lets for instance say your client loads some existing 3 todo items. Then the user modifies one of them, deletes another one and adds a new one. You can either do that in three requests or one single request with add/modify/delete operations encoded in it. Both ways are valid and the best solution depends on your use case and constraints like bandwidth, processing power and network round-trip time.

Can a single url have two different objects (single item or collect of items) be posted and still be RESTfully designed?

I have person json objects that are posted to a rest service that is responsible for creating the objects and storing them in a database. But I have two situations I need to handle.
Post a single person object and have one person created
Post a person array and have multiple people created
Can I use the same url...ie www.mysite.com/people/ and have the server determine whether it is a single person or a collection of people? I know I can technically do this but how should I deal with this situation and still have a RESTful design?
Yes. "POST" is kind of a wildcard, and can "get away" with most anything. What you don't want to do is conflate this resource with the underlying resource. You don't want to POST to /people, rather something specific for the task.
So, you'll want something like /people_loader for this task that returns a explicit result of the process (/people_loader/1234), which is a resource linking to the new people you just created.
/people is your base resource, so a /people_loader result would be a collection of /people links, and perhaps some other information for those objects that weren't loaded (do to errors or other constraints).

How to design a RESTful collection resource?

I am trying to design a "collection of items" resource. I need to support the following operations:
Create the collection
Remove the collection
Add a single item to the collection
Add multiple items to the collection
Remove a single item from the collection
Remove multiple items from the collection
This is as far as I have gone:
Create collection:
==>
POST /service
Host: www.myserver.com
Content-Type: application/xml
<collection name="items">
<item href="item1"/>
<item href="item2"/>
<item href="item3"/>
</collection>
<==
201 Created
Location: http://myserver.com/service/items
Content-Type: application/xml
...
Remove collection:
==>
DELETE /service/items
<==
200 OK
Removing a single item from the collection:
==>
DELETE /service/items/item1
<==
200 OK
However, I am finding supporting the other operations a bit tricky i.e. what methods can I use to:
Add single or multiple items to the collection. (PUT doesn't seem to be right here as per HTTP 1.1 RFC
Remove multiple items from the collection in one transaction. (DELETE doesn't seem to right here either)
You would be better off using a non-positional identifier such as a UUID for collection items, to avoid problems such as the url of an item changing when you delete an item that precedes it. (Of course, you can still use itemN or just N, as long as the number stays attached to the same item at all times, leaving gaps after deletions, but a UUID is less confusing.)
The collection has the url /service/items/. Each item has the url /service/items/<id>.
Creating items and collections is a POST on the parent of the resource.
You could use a PUT if the client has the right and ability to generate the name or id of the resource.
Removing items and collections is a DELETE on the resource itself.
Adding multiple items is either multiple POST or a multi-item POST on the parent (the collection).
Removing multiple items is a DELETE on each resource. I would discourage multi-item DELETE for two reasons:
Bulk deletion is a dangerous operation (for which reason, I would also discourage DELETE on a non-empty collection).
The only meaningful target of the operation is the parent collection, thus making bulk DELETE asymmetric with respect to single-item DELETE.
If you really need bulk deletion capability, provide it through a different, clearly marked API, such as PURGE /service/items.
to add items to the collection, you POST them to the collection's URL (http://myserver.com/service/items). in your case, you already have a 'multiple items' representation in XML, just POST that.
I don't know a simple way to remove multiple items on a single operation... may you could PUT to the collection's item with a list of id's to retain. the idea being that PUT updates the container, so what's not there is removed. and, i think it's not useful to provide the whole data you want to keep, just the references of the items.
What's wrong with PUT to create an element? You cited the HTTP RFC, but the HTTP RFC doesn't preclude the use of PUT to create an element in your collection, as far as I know. If I've missed something, please make a specific citation, with an excerpt.
The key difference between PUT and POST to create elements:
PUT should be an idempotent operation; POST is not.
For deleting multiple elements in a single transaction, you can send DELETE to a URL that specifies a range (/service/items/13-20, or you can send DELETE to /service/items and use the HTTP Range header (See RFC2616 sec. 14.35.2). Normally the range header is contrued to imply a byte range, and is used on a GET request, but it's up to your resource to infer the meaning of RANGE on a DELETE.
Why not use the AtomPub spec and adhere to the decisions written there? This way new clients could easily consume your data (using GData libraries..simple) and things like paged data feeds and the symantics of GET/POST/PUT/DELETE are solidly defined. Just my $.02.
Use Content-Type /text/uri-list and manage with PUT,GET,PATCH,DELETE a list
of links to the resources you want to collect.
The PATCH format you need could be very simple: just prefix with "+ " or "- " the modality of the change each uri bring to the collection.
Unfortunately, this media type, which could be named text/uri-list-update, is not yet officially registered, to my knowledge.