Resources in APIRestful - rest

I have read several things about API's but there is something that is not clear to me on the subject of how to structure the resources. I will give you an easy but illustrative example. We imagine we have this relationship:
|Clients| (1:1) ------<>----- (0:M) |Orders| (1:1) ------<>------ (1:1) |Statuses|
A client can have zero or many orders and each order has a status.
The question comes when making resources, the resources that are clear are as follows:
GET /clients (get a list)
GET /clients/10 (get detail of one client)
POST /clients (create a client passing data by BODY)
(there could be more like the PUT but to simplify the example I simplify.)
The question is, to get the Orders from a Customer such as the resource?
GET /clientes/10/orders
Or in place:
GET /orders?id_cliente=10
The same to get the detail of an Order, what would it be like?
GET /clientes/10/orders/10
Or it would simply make sense to do this (which would also show the information of the State that you have):
GET /orders/10
Or when you want to delete an order:
DELETE /orders/10
or
DELETE /clientes/10/orders/10
And to create an Order, should the Customer always exist or could a Order and a Customer be created at the same time with the following resource? For example, a Customer not registered when making a purchase will place the Order and register at the same time)
POST /orders
Passing the Customer data in the BODY to it as the Order data would go. First the Customer would be created and then the Order.
If there is anyone who knows what all the valid resources of the sample relationship would look like, it would be good to share them. I don't want to get into paginate topics or other topics that are also important in an API. Only in the matter of resources.

To resolve you confusion, you can just ask yourself the following questions.
Does my resource have a unique resource id? - There should not be multiple resource elements pointing to a same resource.
Whether child resource can exist without the parent? - If it can exist, then it should not be considered as a child resource, but has to be concluded as individual resources.
In your case, according to the above, it is clear that the clients resource is a parent of orders resource. So the API endpoints must be,
/clients (GET) - get all clients
/clients/$client_id (GET) - get a client
/clients/$client_id/orders (GET) - get all orders of the particular client
/clients/$client_id/orders (POST) - create new order for the client
/clients/$client_id/orders/$order_id (PUT) - Modify the particular order for the client
/clients/$client_id/orders/$order_id (DELETE) - Delete the particular order for the client
And for your last question on creating a parent resource when a child resource create api called,
Refer my answer
Note : Sorting, filtering, limits and pagination can be supported using query parameters in your APIs.

Related

RESTful API with relationships

Lets assume I'm building an API for a restaurant and I have the following resources:
Donut(has_chocolate,has_sprinkles)
and
Receipt(cost,donut_id)
My Web App will want to display a table of receipts for the manager to view. Unfortunately the receipt object by itself isn't useful enough, the manager needs to see whether the donut has chocolate or not.
How best do I do this - I can think of 3 implementations:
1) Do a JOIN and return the receipt resource with the has_chocolate additional field
2) Do a JOIN and return the receipt resource with a donut object containing ALL relevant donut information
3) Pull in a page of receipt objects, collect and de-duplicate the donut_ids, and use them to pull in the required donut objects - either one at a time /donut/id, or all at once /donuts?ids=id1,id2,id3
A RESTful API should have endpoints that resolve to a resource or a collection of resources. You can then do an HTTP verb on that endpoint, in this case a GET. Therefore you need to make a decision about how do you define your resources for the API user?
Are there two resources, donuts and receipts, like in your SQL?
Do you want to define a donut as a resource that has a receipt as one of the fields?
Either is fine, the problem is when you start making routes that are a resource 'with something extra on top'. That starts to become hard for the consumer to understand and not RESTful.
If it were me I would choose option 3.
Define two separate endpoints for collections of donuts and receipts: /v0/donuts/ and /v0/receipts/
Allow the consumer to join on the client side by exposing the neccessary filters /v0/donuts/?ids=1,2,3,8
You could make a /v0/events/< id>/ route but seeing as the use-case is to always get a batch of donuts then this would result in too many round-trips for the consumer.
It also sounds like you want to paginate these collections. In this case you should define a max_page_size, default_page_size and you should return your client a next_page field in the response (which is null if it's the last page). You would also have to decide what to paginate on, probably the id in this case.

Is it considered RESTful if single POST requests create multiple resources?

We have customers API that takes {customer-name, customer-mobile, customer-email} and creates customer in the database.
We also have order API that takes {productId, customer-name, customer-mobile, customer-email}.
The code for order API:
First creates customer based on {name,mobile,email} passed in the order API and return back customerId.
The {productId, customerId} further gets saved in the database in the order table.
Is this restful practice that one API is internally first creating some other resource?
Please note that its an over simplified example where API expects only one type of product in the order API.
It's fine for a single POST call to result in multiple resources being created. It's not generally the best idea but there are use cases where it makes sense - example cases might include (usual legal disclaimer... not limited to...)
the POST method is to the parent resource of all the created resources. So, a POST /accounts call might result in an /accounts/<accountId> resource being created but also an /accounts/<accountId>/tweets resource. In this instance, the /accounts/<accountId> parent is the 'actual' resource being created.
the POST method might create multiple resources representing multiple ways in which the resource may interact with other parts of the system. So, a POST /accounts response might create resources under /accounts/<accountId> and /users/<accountId> (because an account is-a user and user id are a super set of account ids, for arguments sake). However, the client really only gets told about the one under the '/accounts' path (via the Location header). The other created resource is basically a side-effect.
The key point, really, is that the POST method returns a single Location header - representing the 'primary' resource created - and that subsequent 'GET's on that URI are capable of locating any the other resources via links.
If you find yourself in a situation where creating multiple resources via a single POST request results in you having to return different values for the Location header, then something's wrong with your resource breakdown. It should be clear that a 'POST' will always create one particular type of resource, a URI to being returned in the header. Other resources might be created as side-effects.

Rest API: path for accessing derived data

It is not clear to me that if I have a micro service that is in place to provide some derived data how the rest api should be designed for this. For instance :-
If I have a customer and I want to access the customer I would define the API as:
/customer/1234
this would return everything we know about the customer
however if I want to provide a microservice that simply tells me if the customer was previously known to the system with another account number what do I do. I want this logic to be in the microservice but how do I define the API
customer/1234/previouslyKnow
customerPreviouslyKnown/1234
Both don't seem correct. In the first case it implies
customer/1234
could be used to get all the customer information but the microservice doesn't offer this.
Confused!
Adding some extra details for clarification.
I suppose my issue is, I don't really want a massive service which handles everything customer related. It would be better if there were lighter weight services that handles customer orders, customer info, customer history, customer status (live, lost, dead....).
It strikes me all of these would start with
/customer/XXXX
so would all the services be expected to provide a customer object back if only customer/XXXX was given with no extra in the path such as /orders
Also some of the data as mentioned isn't actually persisted anywhere it is derived and I want the logic of this hidden in a service and not in the calling code. So how is this requested and returned.
Doing microservices doesn't mean to have a separate artifact for each method. The rules of coupling and cohesion also apply to the microservices world. So if you can query several data all related to a customer, the related resources should probably belong to the same service.
So your resource would be /customers/{id}/previous-customer-numbers whereas /customers (plural!) is the list of customers, /customers/{id} is a single customer and /customers/{id}/previous-customer-numbers the list of customer numbers the customer previously had.
Try to think in resources, not operations. So returning the list of previously used customer numbers is better than returning just a boolean value. /customer/{id}/previous-accounts would be even better, I think...
Back to topic: If the value of previous-accounts is directly derived from the same data, i.e. you don't need to query a second database, etc. I would even recommend just adding the value to the customer representation:
{
"id": "1234",
"firstName": "John",
"lastName": "Doe",
"previouslyKnown": true,
"previousAccounts": [
{
"id": "987",
...
}
]
}
Whether the data is stored or derived shouldn't matter so the service client to it should not be visible on the boundary.
Adding another resource or even another service is unnecessary complexity and complexity kills you in the long run.
You mention other examples:
customer orders, customer info, customer history, customer status (live, lost, dead....)
Orders is clearly different from customer data so it should reside in a separate service. An order typically also has an order id which is globally unique. So there is the resource /orders/{orderId}. Retrieving orders by customer id is also possible:
/orders;customer={customerId}
which reads give me the list of orders for which the customer is identified by the given customer id.
These parameters which filter a list-like rest resource are called matrix parameters. You can also use a query parameter: /orders?customer={customerId} This is also quite common but a matrix parameter has the advantage that it clearly belongs to a specific part of the URL. Consider the following:
/orders;customer=1234/notifications
This would return the list of notifications belonging to the orders of the customer with the id 1234.
With a query parameter it would look like this:
/orders/notifications?customer=1234
It is not clear from the URL that the orders are filtered and not the notifications.
The drawback is that framework support for matrix parameters is varying. Some support them, some don't.
I'd like matrix parameters best here but a query parameter is OK, too.
Going back to your list:
customer orders, customer info, customer history, customer status (live, lost, dead....)
Customer info and customer status most likely belong to the same service (customer core data or the like) or even the same resource. Customer history can also go there. I would place it there as long as there isn't a reason to think of it separately. Maybe customer history is such a complicated domain (and it surely can be) that it's worth a separate service: /customer-history/{id} or maybe just /customer/{id}.
It's no problem that different services use the same paths for providing different information about one customer. They are different services and they have different endpoints so there is no collision whatsoever. Ideally you even have a DNS alias pointing to the corresponding service:
https://customer-core-data.service.lan/customers/1234
https://customer-history.service.lan/customers/1234
I'm not sure if I really understand your question. However, let me show how you can check if a certain resource exist in your server.
Consider the server provides a URL that locates a certain resource (in this situation, the URL locates a customer with the identifier 1): http://example.org/api/customers/1.
When a client perform a GET request to this URL, the client can expect the following results (there may be other situation, like authentication/authorization problems, but let's keep it simple):
If a customer with the identifier 1 exists, the client is supposed to receive a response with the status code 200 and a representation of the resource (for example, a JSON or XML representing the customer) in the response payload.
If the customer with the identifier 1 do not exist, the client is supposed to receive a response with the status code 404.
To check whether a resource exists or not, the client doesn't need the resource representation (the JSON or XML that represents the customer). What's relevant here is the status code: 200 when the resource exists and 404 when the resource do not exist. Besides GET requests, the URL that locates a customer (http://example.org/api/customers/1) could also handle HEAD requests. The HEAD method is identical to the GET method, but the server won't send the resource representation in HEAD requests. Hence, it's useful to check whether a resource exists or not.
See more details regarding the HEAD method:
4.3.2. HEAD
The HEAD method is identical to GET except that the server MUST NOT
send a message body in the response (i.e., the response terminates at
the end of the header section). The server SHOULD send the same
header fields in response to a HEAD request as it would have sent if
the request had been a GET, except that the payload header fields MAY be omitted. This method can be used for obtaining
metadata about the selected representation without transferring the
representation data and is often used for testing hypertext links for
validity, accessibility, and recent modification. [...]
If the difference between resource and resource representation is not clear, please check this answer.
One thing I want to add to the already great answers is: URLS design doesn't really matter that much if you do REST correctly.
One of the important tenets of REST is that urls are discovered. A client that has the customers's information already, and wants to find out what the "previously known" information, should just be able to discover that url on the main customer resource. If it links from there to the "previously known" information, it doesn't matter if the url is on a different domain, path, or even protocol.
So if you application naturally makes more sense if "previouslyKnown" is on a separate base path, then maybe you should just go for that.

RESTful approach for updating resource and creating associated objects

I'm designing a REST-style API for a service that provides analysis of clinical data. The API allows a user to create a Patient resource. This resource provides input data to the server-side analysis.
Creation of a Patient is neither safe nor idempotent (the server assigns an ID) so POST is used, POST Patients
The Patient resource can be large, so it has sub-resources, e.g. Medications, that can be updated. Updating Medications is idempotent as the entire set of med's will be replaced, so PUT is used.
Clinical analysis is triggered by requesting POST /Patients/{patientId}/analysisResults . Alternatively, a user can request that analysis results are returned in the response of the POST /Patients request; this saves an additional HTTP round-trip.
My problem is this; users want results of the analysis included in the response to an update (PUT) to Patient/Medications - understandable as they don't want to make a second request to retrieve the results. Thus PUT Patient/Medications would be idempotent with regards to the Patient resource but not in terms of all resources as a new analysisResults sub-resource will be created. Should I:
a) Enable this with a PUT.
b) Enable this with a POST.
c) Insist that a separate call is required to create new
analysisResults even though this will increase the overall
response times for the end-user?
Option C if you wish to remain RESTful.
Options A and B will most likely weaken the properties that REST is designed to give you, caching is the one that comes directly to mind.
If this is HTML based, the response will include a link to the analysisReport resource to allow the user to drive the application to somewhere useful.

RESTful idempotence

I'm designing a RESTful web service utilizing ROA(Resource oriented architecture).
I'm trying to work out an efficient way to guarantee idempotence for PUT requests that create new resources in cases that the server designates the resource key.
From my understanding, the traditional approach is to create a type of transaction resource such as /CREATE_PERSON. The the client-server interaction for creating a new person resource would be in two parts:
Step 1: Get unique transaction id for creating the new PERSON resource:::
**Client request:**
POST /CREATE_PERSON
**Server response:**
200 OK
transaction-id:"as8yfasiob"
Step 2: Create the new person resource in a request guaranteed to be unique by using the transaction id:::
**Client request**
PUT /CREATE_PERSON/{transaction_id}
first_name="Big bubba"
**Server response**
201 Created // (If the request is a duplicate, it would send this
PersonKey="398u4nsdf" // same response without creating a new resource. It
// would perhaps send an error response if the was used
// on a transaction id non-duplicate request, but I have
// control over the client, so I can guarantee that this
// won't happen)
The problem that I see with this approach is that it requires sending two requests to the server in order to do to single operation of creating a new PERSON resource. This creates a performance issues increasing the chance that the user will be waiting around for the client to complete their request.
I've been trying to hash out ideas for eliminating the first step such as pre-sending transaction-id's with each request, but most of my ideas have other issues or involve sacrificing the statelessness of the application.
Is there a way to do this?
Edit::::::
The solution that we ended up going with was for the client to acquire a UUID and send it along with the request. A UUID is a very large number occupying the space of 16 bytes (2^128). Contrary to what someone with a programming mind might intuitively think, it is accepted practice to randomly generate a UUID and assume that it is a unique value. This is because the number of possible values is so large that the odds of generating two of the same number randomly are low enough to be virtually impossible.
One caveat is that we are having our clients request a UUID from the server (GET uuid/). This is because we cannot guarantee the environment that our client is running in. If there was a problem such as with seeding the random number generator on the client, then there very well could be a UUID collision.
You are using the wrong HTTP verb for your create operation. RFC 2616 specifies the semantic of the operations for POST and PUT.
Paragraph 9.5:
POST method is used to request
that the origin server accept the
entity enclosed in the request as
a new subordinate of the resource
identified by the Request-URI in the Request-Line
Paragraph 9.6
PUT method requests that the
enclosed entity be stored under the
supplied Request-URI.
There are subtle details of that behavior, for example PUT can be used to create new resource at the specified URL, if one does not already exist. However, POST should never put the new entity at the request URL and PUT should always put any new entity at the request URL. This relationship to the request URL defines POST as CREATE and PUT as UPDATE.
As per that semantic, if you want to use PUT to create a new person, it should be created in /CREATE_PERSON/{transaction_id}. In other words, the transaction ID returned by your first request should be the person key used to fetch that record later. You shouldn't make PUT request to a URL that is not going to be the final location of that record.
Better yet, though, you can do this as an atomic operation by using a POST to /CREATE_PERSON. This allows you with a single request to create the new person record and in the response to get the new ID (which should also be referred in the HTTP Location header as well).
Meanwhile, the REST guidelines specify that verbs should not be part of the resource URL. Thus, the URL to create new person should be the same as the location to get the list of all persons - /PERSONS (I prefer the plural form :-)).
Thus, your REST API becomes:
to get all persons - GET /PERSONS
to get single person - GET /PERSONS/{id}
to create new person - POST /PERSONS with the body containing the data for the new record
to update existing person or create new person with well-known id - PUT /PERSONS/{id} with the body containing the data for the updated record.
to delete existing person - DELETE /PERSONS/{id}
Note: I personally prefer not using PUT for creating records for two reasons, unless I need to create a sub record that has the same id as an already existing record from a different data set (also known as 'the poor man's foreign key' :-)).
Update: You are right that POST is not idempotent and that is as per HTTP spec. POST will always return a new resource. In your example above that new resource will be the transaction context.
However, my point is that you want the PUT to be used to create a new resource (a person record) and according to the HTTP spec, that new resource itself should be located at the URL. In particular, where your approach breaks is that the URL you use with the PUT is a representation of the transactional context that was created by the POST, not a representation of the new resource itself. In other words, the person record is a side effect of updating the transaction record, not the immediate result of it (the updated transaction record).
Of course, with this approach the PUT request will be idempotent, since once the person record is created and the transaction is 'finalized', subsequent PUT requests will do nothing. But now you have a different problem - to actually update that person record, you will need to make a PUT request to a different URL - one that represents the person record, not the transaction in which it was created. So now you have two separate URLs your API clients have to know and make requests against to manipulate the same resource.
Or you could have a complete representation of the last resource state copied in the transaction record as well and have person record updates go through the transaction URL for updates as well. But at this point, the transaction URL is for intends and purposes the person record, which means it was created by the POST request in first place.
I just came across this post:
Simple proof that GUID is not unique
Although the question is universally ridiculed, some of the answers go into deeper explanation of GUIDs. It seems that a GUID is a number of 2^128 in size and that the odds of randomly generating two of the same numbers of this size so low as to be impossible for all practical purposes.
Perhaps the client could just generate its own transaction id the size of a GUID instead of querying the server for one. If anyone can discredit this, please let me know.
I'm not sure I have a direct answer to your question, but I see a few issues that may lead to answers.
Your first operation is a GET, but it is not a safe operation as it is "creating" a new transaction Id. I would suggest POST is a more appropriate verb to use.
You mention that you are concerned about performance issues that would be perceived by the user caused by two round trips. Is this because your user is going to create 500 objects at once, or because you are on a network with massive latency problems?
If two round trips are not a reasonable expense for creating an object in response to a user request, then I would suggest HTTP is not the right protocol for your scenario. If however, your user needs to create large amounts of objects at once, then we can probably find a better way of exposing resources to enable that.
Why don't you just use a simple POST, also including the payload on your first call. This way you save on extra call and don't have to spawn a transaction:
POST /persons
first_name=foo
response would be:
HTTP 201 CREATED
...
payload_containing_data_and_auto_generated_id
server-internally an id would be generated. for simplicity i would go for an artifial primary key (e.g. auto-increment id from database).