Design a RESTful api for creating a resource and its related resources at once - rest

I want to know how to design a RESTFUL api for creating a resource and its related resources at once.
For example, I want to create an order which contains a list of items using my RESTFUL API, for example:
{
order_id:1,
description: "XXX",
items: [
{item_id:1, price:30, ...},
{item_id:2, price:40, ...}
]
}
One way is giving two api
post: api/orders => create a new order and return the order id
post: api/orders/id/items => create related items using the order_id
However, the order and items should be created together. So if the second api failed, it will create an order without any item inside and it is the situation I don't want to see. Actually, I want the backend server to do a transaction and create the order and items at once, it should be succeeded or failed together.
So, is it a good way to put the items in the body of request, and post only once to api/orders ? Or is there other better design for this situation?
Thank you!

I want to know how to design a RESTFUL api for creating a resource and its related resources at once.
Perfectly reasonable thing to do. Concentrate your attention on how to describe to the client how to create the appropriate request, and how to interpret the document describing the result.
The clue is in the definition of the 201 Created status code
The 201 (Created) status code indicates that the request has been fulfilled and has resulted in one or more new resources being created.
The 201 response payload typically describes and links to the resource(s) created.
(emphasis added)
In the case of the web, the way we would do this is to have a form; the client would provide information in the form and submit it. The browser, following the standard for form processing, would generate a POST (because the semantics are unsafe) request with the form data encoded within the message body and the appropriate content type defined in the header (for instance application/x-www-form-urlencoded).
The response, in term, would be an HTML document with a bunch of links to all of the interesting resources that were created.
Does it have to be HTML? No, of course not - you could use text/plain if it suited your needs. You have somewhat better long term prospects when using a media type that has built into it a notion of links that general purpose components will understand.

Definitely, creating order without items - bad idea. This will ends up with not solid API and not consistent entities. Also, you can't create items using api/orders URI, because this violates the basis of the REST principles.
For your business logic REST API may looks like:
POST api/item
{
price: 40,
name: "xxx",
...
}
<<<<< 201
{
id: 1
}
GET api/item/{id}
<<<<< 200
{
id: 4,
price: 40,
name: "xxx",
...
}
POST api/order
{
description: "xxx",
items: [
{id: 1, count: 5},
{id: 23456, count: 1}
]
}
<<<<< 201
{
id: 123442
}
I think it's unnecessary to put full items in creating order request body. Item ID's will be enough to create order-item bindings on backend.

Related

What is the standard practice for designing REST API if it is being used for inserting / updating a list of records

We are building an API which will be used for inserting and updating the records in a database. So if the record exists based on the Key the record will be updated and if it does not then it will be inserted.
I have two questions.
As per REST guidelines, what are the options for designing such an API e.g. PUT / POST OR PATCH? How should the list of objects be represented?
NOTE: I know from other answers that I read that there is confusion over how it should be as per REST guidelines. So I am OK if I can get some guidance on general best practice (irrespective of REST part)
Secondly, the part where I am really confused about is how to represent the output of this or what this API should return.
Specific guidance/inputs on above topic would be really appreciated.
I've seen many different implementations for inserts/updates across various vendors (Stripe, HubSpot, PayPal, Google, Microsoft). Even though they differ, the difference somehow fits well with their overall API implementation and is not usually a cause for stress.
With that said, the "general" rule for inserts is:
POST /customers - provide the customer details within the body.
This will create a new customer, returns the unique ID and customer details in the response (along with createdDate and other auto-generated attributes).
Pretty much most, if not all API vendors, implement this logic for inserts.
Updates, are quite different. Your options include:
POST
POST /customer/<customer_id> - include attributes and values you want to update within the body.
Here you use a POST to update the customer. It's not a very common implementation, but I've seen it in several places.
PUT
PUT/customer/<customer_id> - include either all, or partially updated attributes within the body.
Given PUT is technically an idempotent method, you can either stay true to the REST convention and expect your users to provide all the attributes to update the resource, or make it simpler by only accepting the attributes they want to update. The second option is not very "RESTful", but is easier to handle from a users perspective (and reduces the size of the payload).
PATCH
PATCH /customer/<customer_id> - include the operation and attributes that you want to update / remove/ replace / etc within the body. More about how to PATCH.
The PATCH method is used for partial updates, and it's how you're "meant" to invoke partial updates. It's a little harder to use from a consumers perspective.
Now, this is where the bias kicks-in. I personally prefer to use POST, where I am not required to provide all the attributes to invoke an update (just the ones I want to update). Reason is due to simplicity of usage.
In terms of the response body for the updates, usually they will return object within the response body include the updated attributes (and updated auto-generated attributes, such updatedDate).
Bulk inserts/ updates
Looking at the Facebook Graph HTTP API (Batch Request) for inspiration, and assuming POST is your preferred method for updates, you could embed an array of requests using a dedicated batch resource as an option.
Endpoint: POST /batch/customers
Body:
{
["first_name": "John", "last_name": "Smith"...], //CREATE
["id": "777", "first_name": "Jane", "last_name": "Doe"...], //UPDATE
["id": "999", "first_name": "Mike", "last_name": "Smith"...], //UPDATE
[....]
}
Sample Response
{
"id": "123",
"result":[
{ // Creation successful
"code": 200,
"headers":{..},
"body": {..},
"uri": "/customers/345"
},
{ // Update successful
"code": 200,
"headers":{..},
"body": {..},
"uri": "/customers/777",
},
{ // A failed update request
"code": 404,
"headers":{..},
"body": {..}, // body includes error details
}
]
}

RESTful API design, naming drafting endpoints

When naming an endpoint for creating a "draft" version of a resource which is best practice?
POST >> /posts
{
title: 'My Post',
body: 'The content of my post',
status: 'DRAFT',
}
Or is it better to:
POST >> /posts/drafts
{
title: 'My Post',
body: 'The content of my post',
}
From what I saw on the payload, the DRAFT is just status of the resource. you can use PUT to update it.
would you explain more on why you want to DRAFT in the URI path?
As with most of the things I'd say it depends. The general assumption when working with REST is that you've got collections of resources. That's why the most common naming convention is to use plurals when naming endpoints.
When I see and endpoint called /posts I'd assume that by doing a GET to it I would receive a collection of posts. Similarly by calling /posts/{id} I should receive a post with a particular id.
Resource collections are also embedded in each other - when I see an endpoint /posts/{id}/drafts I'd assume that I would get drafts for a post with a given id.
Now the question is this - do you want to treat your data as two separate collections (which you would have to synchronize somehow) or do you want to stick with this being embedded collections? If the first then you could have two endpoints /posts and /drafts. If the second then you should go with the root endpoint /posts and then /posts/{id}/drafts.
However if a post doesn't have a collection of drafts, you could just simply go with a single /posts endpoint and don't specify any additional things, as this will mess up the design of your API. Just as in your first proposition.

Is REST a good solution for my application? - (a system with many actions)

I am starting a new project and I was trying to figure out if I should follow a RESTful approach or not. By reading different sources on the internet I am getting more and more confused on how a truly RESTful approach should be. Some people say that the REST request (ie, both the URI and the rest of the content of the HTTP request) should never describe an action with something other than the HTTP verbs. Some others say that since the HTTP verbs are limited, the HTTP request body can provide additional info regarding which action need to be applied on the data described by the URI. Which of the two is correct? I will give you a simplified description of the software I am trying to build and how I think it should implemented with REST: The user must be able to upload/delete/edit data on the server. Then, he must be able to perform 10 different kinds of analysis (analysis01-analysis10) on the server in the form of jobs. So, the user will be submitting jobs to the server. When the jobs are finished the user will be able to get the results of the analysis. So here is how I think is the right way of implementing this in REST:
Datasets:
POST /datasets/ - To create/upload a new dataset
GET /datasets/ - To get a list of all the available datasets.
GET /datasets/01 - To get info about dataset 01
DELETE /datasets/01 - To delete dataset 01
Jobs:
POST /analysis01_jobs/ - Submit a new job for analysis01
GET /analysis01_jobs/ - Get a list with all the submitted analysis01 jobs
GET /analysis10_jobs/ - Get a list with all the submitted analysis10 jobs
GET /analysis01_jobs/01 - Get the status of job '01' which performs analysis of type 01
DELETE /analysis10_jobs/01 - Delete/Cancel job '01' which performs analysis of type 10
As you can see each type of analysis has a different REST URL path for the jobs. I was thinking to change this and put all jobs under the same path: "/analysis_jobs/" and specify the type of analysis I want inside the HTTP header. But this will imply the type of action I want the server to perform. Thus this this is not RESTful any more. Right or wrong?
When a job is complete it will produce a "result" resource. So the REST API for this will be something like this:
- There is no POST here because only the job that runs on the server can generate results.
GET /analysis01_results/ - To get a list of all the available results from analysis01 jobs
GET /analysis01_results/01 - To get the results of a job that performed analysis of type 01. The body of the HTTP response will also contain info about the "parent" job and data.
DELETE /analysis01_results/01 - To delete the above results.
Is the above design RESTful?
Thank you in advance!
REST is about machine to machine communication. If you don't have at least 2 different clients I don't think it will worth the effort to implement a REST service.
Some people say that the REST request (ie, both the URI and the rest of the content of the HTTP request) should never describe an action with something other than the HTTP verbs. Some others say that since the HTTP verbs are limited, the HTTP request body can provide additional info regarding which action need to be applied on the data described by the URI. Which of the two is correct?
You should read the Fielding dissertation, it is the only true source of knowledge. :D
Both can be wrong. The second one is closer to the truth. If you need to describe a new action, you can always define a new resource and use it with the existing HTTP verbs. For example ANALYZE /datasets/1 can be described with POST /analysis/ {dataset: {id: 1}}.
Be aware that we are talking here about hyperlinks:
POST /datasets/ - To create/upload a new dataset
This is an action, but this is a hyperlink as well in the representation of the /datasets/, which you can access with GET /datasets/. What you can add to the body is the To create/upload a new dataset part, so the client won't need to know anything about the URI structure to understand what the link does.
{
href: "/datasets/",
method: "POST",
rel: "/docs/datasets/create"
}
You can access the form description with GET /docs/datasets/create. (Currently ppl are working on a standard format, to describe these descriptions, e.g. RDF + Hydra. But that is not production ready currently.)
Ofc. you can expand the description if you want:
{
href: "/datasets/",
method: "POST",
rel: "/docs/datasets/create",
label: "Create a new dataset",
description: "You can create a new dataset by sending this form.",
fields: {
label: {
type: "string",
label: "Title",
description: "You can give a title to the dataset here.",
...
},
records: {
type: "array",
...
}
}
}
but it is easier to generate a documentation if you describe everything in a docs file, probably in JSON-LD for the REST clients and in HTML for the 3rd party developers of the clients.
POST /analysis01_jobs/ - Submit a new job for analysis01
GET /analysis01_results/ - To get a list of all the available results from analysis01 jobs
GET /analysis01_results/01 - To get the results of a job that performed analysis of type 01. The body of the HTTP response will also contain info about the "parent" job and data.
I would rather use
POST /jobs/ {analysis: {id: "01"}}
GET /analysis/01/jobs
GET /jobs/2345/result
You are going in the right direction but still you can moderate it.
1-
Is REST a good solution for my application?
Yes and you can compare it .REST vs SOAP on this question
2-
Use PUT for Creating or Adding a resource or Job instead of POST.
Resources are manipulated using a fixed set of four create, read, update, delete operations: PUT, GET, POST, and DELETE. PUT creates a new resource, which can be then deleted by using DELETE. GET retrieves the current state of a resource in some representation. POST transfers a new state onto a resource. See Responding to HTTP Methods and Requests for more information.
Source Oracle docs

Saving two new related objects in one request

I have two models in Django:
class Thread(models.Model):
entity = models.ForeignKey(Entity, null=True, blank=True)
...
class ThreadMessage(models.Model):
thread = models.ForeignKey(Thread, related_name='messages')
author = models.ForeignKey(User)
...
Now a client wants to create a new thread with first message in it. It has first to do a POST /threads to create a new thread and find out its id and then do POST /messages passing the found id in thread field.
I am thinking if it's reasonable and possible to do all of this in one request from Ember like:
POST /messages
{"message": {"text": "text", ...},
"thread": {"entity": 1}}
And the response would be:
{"message": {"text": "text", "id": 5678, "thread": 1234, ...},
"thread": {"entitity": 1, "id": 1234, ...}}
Yes it is perfectly reasonable.
People seem to interpret REST in a very strange and largely ignorant way. A cursory read of the HTTP RFC 7231 for POST and PUT will confirm you are on solid ground.
A resource representation can represent ANYTHING. The key thing is to preserve the semantics of the REST operations. So PUT can be used for both CREATE and REPLACE like operations (I tend to think of PUT being REPLACE rather than UPDATE as REPLACE is closer to an idempotent semantic than UPDATE in my mind)
A PUT to an endpoint where supported, should accept whatever representation a GET returns. A POST can do literally anything you want as it doesn't need to support idempotent semantics.
HTTP and REST is designed and intended to support resource representations that may overlap other resources and the RFC is explicit about this. You do this all the time when doing a GET on a collection endpoint.
You are NOT breaking REST by having a thread containing a child message in a single request and IMO that is a very valid use use case for sane referential integrity on the server. Any time a transactional semantic is required, a POST or PUT is perfectly valid to create a graph of objects on the server in a single request. It is really simple, if you can GET it in a single request, you should be able to PUT it in a single request, so think carefully about your URL's and parameters.
For example, you may have a thread endpoint that returns all messages and that endpoint may support a parameter to just return some subset of the information /api/threads?include=hasRead which returns just id and hasRead for each message in the thread, or perhaps just some range of 'pages'. You can then PUT using that same endpoint and parameters and just update thehasRead property in bulk.
Anyone who gets hung up on this has probably never considered access controls either. Access control necessitates a different view of a resource from one user to another based on what they are allowed to access. This different view of a resource is conveyed in HTTP auth headers and/or in the request URL; again REST is not being broken by sub-setting or overlapping resources.
So go ahead and create the minimal graph of objects you need and either PUT or POST them. I use V4 UUID's so clients can assign ID's (and thus resource endpoints) themselves and this allows me to use PUT for both create and replace like actions and wire up complex object graphs without client<->server id mapping issues.
What you are trying to do will be break concept of REST and EmberJS itself.
If you have two separate APIs you should make two REST calls.
First save the parent thread model , after successful return save the child message. Then use addObject to reflect changes in views.
This is best way. Don't try to optimize by reducing API calls here and breaking REST in the way.

Serialize objects to complete JSON, not only URI

is it possible to enumerate all instances of a resource without voilating rest principles in a single call.
Say I want to enumerate all the student information using one call.
GET /students
With REST principles this call is returning:
"students": [{
"uri":"/student/1"
},
{
"uri":"/student/2"
},
]
What I want is to use a single call to get all the data:
GET /student
"students": [{
"name":"x",
"moreInfo":...,
"uri":"/student/1"
},
{
"name":"y",
"moreInfo":...,
"uri":"/student/2"
}, ]
This would not violate HTTP principles. Whether it is a good idea or not though is a question for your resource hierarchy, based on what you are trying to do. Such a setup would have a students resource that holds the data for all students. There would be no need then for an individual student record (eg GET /students/:id). The client might get annoyed if this returned a huge amount of data though, and it is pushing the processing of the data onto the client. Say the client only wants one student. It has to parse the entire student population, ignoring all the irrelevant data, to get to the one student it wants. Of course if the client needs all the student data then this isn't an issue.
So really the issue is not how RESTful this is, but why you want to do it and whether it is the right thing for the client of your system. What hierarchy is the client expecting. If this fits then by all means go for it.