I have a resource Task that is exposed via /task
I also have a resource TaskExecutions which is exposed by /taskexecutions
Both resources are entities in my model and I must list the Tasks but recover a field from the TaskExecution via join on a specific field to get the max execution time from the task
My question is:
What is the best design for a rest API in this case?
Should I just add the field on the response or create another resource url that exposes this "composed" resource?
Related
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.
Say I have the need to expose a service, where I can request an analysis of a user over a specific range of time (common actions, activities, relationships, etc.).
I would immediately think of this as:
/users/{userId}/analyses - POST
/users/{userId}/analyses/{analysisId} - GET
The problem here, is where the 'analysis' resource comes into existence - it is inherently request-based as it is the service that will do this complex analysis, and also the service that has the most up-to-date state of the user data. In short, it doesn't exist prior to request.
My current thinking has me at three options for requesting an analysis for the first time (with retrieval being the same):
/users/{userId}/analyses?from=2017-01-01&to=2018-01-01 - GET
/users/{userId}/analyses - POST { "from": "2017-01-01", "to": "2018-01-01" }
/users/{userId}/analyses?from=2017-01-01&to=2018-01-01 - POST
I like the GET with query parameters, as I'm requesting a resource, and scoping the user data to be used, until I recognise that the resource could change between requests (based on data on the back end, or processing logic change), and that I would need to call a second time to POST this resource.
I like the POST with the request body, as I'm expecting a resource to be created, until I recognise that the state I've transferred, is not the state I would get back when I retrieve this later, nor is it even the same hypermedia type.
I like the POST with query parameters and no body, as I'm creating a resource and scoping that resource, but I'm still transferring a state that isn't the resource or end media type, and I've seen practically no other examples of POSTs with query parameters.
Anyone have experience with these kinds of actions in a RESTful manner?
In my opinion, using GET /users/{userId}/analyses?from=...&to=... is a good approach.
You request a resource of type analysis which means you have to use HTTP verb GET. You pass parameters to limit the scope. That the resource might change between two requests is not a problem. You request a resource in a specific state and this state might be changed right after your GET request. Compare this to a collection resource where other clients are allowed to POST something.
Using POST would imply that you want clients to create a resource of type analysis with all necessary data, which is from what I understand not true in your case. Your own counter-arguments for the second and third example are correct, in my opinion.
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.
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.
I have heard both "resource" and "endpoint" to refer to the same thing. It seems that resource is a newer term.
What is the difference between them? Does "resource" imply a RESTful design?
REST
Resource is a RESTful subset of Endpoint.
An endpoint by itself is the location where a service can be accessed:
https://www.google.com # Serves HTML
8.8.8.8 # Serves DNS
/services/service.asmx # Serves an ASP.NET Web Service
A resource refers to one or more nouns being served, represented in namespaced fashion, because it is easy for humans to comprehend:
/api/users/johnny # Look up johnny from a users collection.
/v2/books/1234 # Get book with ID 1234 in API v2 schema.
All of the above could be considered service endpoints, but only the bottom group would be considered resources, RESTfully speaking. The top group is not expressive regarding the content it provides.
A REST request is like a sentence composed of nouns (resources) and verbs (HTTP methods):
GET (method) the user named johnny (resource).
DELETE (method) the book with id 1234 (resource).
Non-REST
Endpoint typically refers to a service, but resource could mean a lot of things. Here are some examples of resource that are dependent on the context they're used in.
URL: Uniform "Resource" Locator
Could be RESTful, but often is not. In this case, endpoint is almost synonymous.
Resource Management
In GCP / AWS, resource is used in reference to cloud infrastructure.
In general computing, a resource is a reference to a component with limited availability.
Dictionary
The definitions provide many more uses of the word.
Something that can be used to help you:
The library was a valuable resource, and he frequently made use of it.
Resources are natural substances such as water and wood which are
valuable in supporting life:
[ pl ] The earth has limited resources, and if we don’t recycle them
we use them up.
Resources are also things of value such as money or possessions that you can use when you need them:
[ pl ] The government doesn’t have the resources to hire the number of
teachers needed.
The Moral
The term resource by definition has a lot of nuance. It all depends on the context its used in.
The terms resource and endpoint are often used synonymously. But in fact they do not mean the same thing.
The term endpoint is focused on the URL that is used to make a request.
The term resource is focused on the data set that is returned by a request.
Now, the same resource can often be accessed by multiple different endpoints.
Also the same endpoint can return different resources, depending on a query string.
Let us see some examples:
Different endpoints accessing the same resource
Have a look at the following examples of different endpoints:
/api/companies/5/employees/3
/api/v2/companies/5/employees/3
/api/employees/3
They obviously could all access the very same resource in a given API.
Also an existing API could be changed completely. This could lead to new endpoints that would access the same old resources using totally new and different URLs:
/api/employees/3
/new_api/staff/3
One endpoint accessing different resources
If your endpoint returns a collection, you could implement searching/filtering/sorting using query strings. As a result the following URLs all use the same endpoint (/api/companies), but they can return different resources (or resource collections, which by definition are resources in themselves):
/api/companies
/api/companies?sort=name_asc
/api/companies?location=germany
/api/companies?search=siemens
Possibly mine isn't a great answer but here goes.
Since working more with truly RESTful web services over HTTP, I've tried to steer people away from using the term endpoint since it has no clear definition, and instead use the language of REST which is resources and resource locations.
To my mind, endpoint is a TCP term. It's conflated with HTTP because part of the URL identifies a listening server.
So resource isn't a newer term, I don't think, I think endpoint was always misappropriated and we're realising that as we're getting our heads around REST as a style of API.
Edit
I blogged about this.
https://medium.com/#lukepuplett/stop-saying-endpoints-92c19e33e819
According https://apiblueprint.org/documentation/examples/13-named-endpoints.html is a resource a "general" place of storage of the given entity - e.g. /customers/30654/orders, whereas an endpoint is the concrete action (HTTP Method) over the given resource. So one resource can have multiple endpoints.
1. Resource description
“Resources” refers to the information returned by an API.
2. Endpoints and methods
The endpoints indicate how you access the resource, while the method indicates the allowed interactions (such as GET, POST, or DELETE) with the resource.
Additional info:
3. Parameters
Parameters are options you can pass with the endpoint (such as specifying the response format or the amount returned) to influence the response.
4. Request example
The request example includes a sample request using the endpoint, showing some parameters configured.
5. Response example and schema
The response example shows a sample response from the request example; the response schema defines all possible elements in the response.
Source-
Reference link
Consider a server which has the information of users, missions and their reward points.
Users and Reward Points are the resources
An end point can relate to more than one resource
Endpoints can be described using either a description or a full or
partial URL
Source: API Endpoints vs Resources