Multiple GET Rest APIs on different fields of a table or One Rest API in DDD - rest

I wanted to provide functionality to clients from my service to get the data based on different fields or sometimes combination of fields. Eg.
getByA
getByB
getByC
getByAandB
getByAandC
In domain driven design, while designing the GET APIs, what should I do out of the following 2:
Should I create individual get api for all such functionalities I wanted to provide?
Should I create one get API with all the possible gets by using all these fields in query parameter. Eg.
get?A=?&B=?&C=?
Which one is the better way to do this? Any suggestions on best practice?

There is a middle path between using individual GET APIs for each of these queries and creating one GET API.
You could use the Specification pattern to expose one GET API, but translate it into a Domain Specification Object before passing it on to the Domain layer for querying. You typically do this transformation in your View Controller, before invoking the Application Service.
Martin Fowler and Eric Evans have published a great paper on using Specifications: https://martinfowler.com/apsupp/spec.pdf
As the paper states, The central idea of Specification is to separate the statement of how to match a candidate, from the candidate object that it is matched against.
Note:
You are fine if you are using this pattern for the Query side as you have outlined in your question, and avoid reusing it in different contexts. For ex., DO NOT use a specification object on both the query side and command side, if you are using (or plan to use) CQRS. You will be creating a central dependency between two parts, that NEED to be kept separate.
Specifications are handy when you want to represent a domain concept. Evaluate your queries (getByAandB and getByAandC) to draw out the question you are asking to the domain (For ex., ask your domain expert to describe the data he is trying to fetch).

Related

What is the RESTful way to design URL that returns parent of a child resource?

I am modeling blogging REST API which has resources Blog, Post and Comment with following URLs:
/api/blogs
/api/blogs/{blogId}
/api/blogs/{blogId}/posts
and I create separate endpoint for all Posts in and their Comment`s:
/api/posts
/api/posts/{postId}
/api/posts/{postId}/comments
Given that I have postId, what is the RESTful way to get Blog for a specific Post? I have three ideas:
1. /api/posts/{postId}/blog
2. /api/blogs/parent-of-post/{postId}
3. /api/blogs?postId={postId}
To me the 1. URL looks more "prettier" but the 2. option looks more "logical" since that endpoint (eg. /api/blogs/*) is generally for blogs resources.
The third option uses query string as parameter but the issue I have with it is that this endpoint would return different type of body depending on the parameter. Eg. without parameter /api/blogs returns a collection of Blog resources, while with parameter postId it would return just single instance of Blog. I am not sure if this is good thing to do (especially because I am using ASP.NET Core and C# which has strongly typed return objects, so implementation might be awkward).
what is the RESTful way to get Blog for a specific Post?
Real answer: anything you want.
REST doesn't care what spelling conventions you use for your resource identifiers. As long as your identifiers conform to the production rules described by RFC 3986, you are good to go.
/api/blogs?postId={postId}
This is a perfectly normal choice, and turns out to be a really convenient one when you want to use general purpose web browsers, because HTML forms already have standards that make it easy to create URI with this shape.
Your other two choices are fine; they lose a point for not being HTML form friendly, but it's still easy enough to describe these identifiers using a URI template.
The third option uses query string as parameter but the issue I have with it is that this endpoint would return different type of body depending on the parameter
General purpose API consumers do NOT assume that two resources are alike just because the spellings of their identifiers overlap each other.
Which is to say, from the outside, there is no implied relationship between
/api/blogs
/api/blogs/1
/api/blogs?postId=2
so the fact that they return different bodies really isn't going to be a surprise to a general purpose consumer.
Now, your routing framework may not support returning different types from the handlers for these resources (or, more likely, may not have any "nice" way to do the routing automatically), but that's an implementation detail deliberately hidden behind the REST API facade.
Similarly, the human beings that read your access log might prefer one spelling to another, to reduce their own cognitive load.

How should I design a REST API

I'm thinking about a REST API design. There are several tables in my database. For example Customer and Order.
Of course - each Order has its Customer (and every customer can have many Orders).
I've decided to provide such an interface
/api/v1/Customers/ -- get list of Customers, add new Customer
/api/v1/Customers/:id: -- get Customer with id=:id:
/api/v1/Orders/ -- get list of Orders, add new Order
/api/v1/Orders/:id: -- get Order with id=:id:
It works flawlessly. But my frontend has to display a list of orders with customer names. With this interface, I will have to make a single call to /api/v1/Orders/ and then another call to /api/v1/Customer/:id: for each record from the previous call. Or perform two calls to /api/v1/Orders/ and /api/v1/Customers/ and combine them on the frontend side.
It looks like overkill, this kind of operation should be done at the database level. But how can/should I provide an appropriate interface?
/api/v1/OrdersWithCustomers
/api/v1/OrdersWithCustomers/:id:
Seems weir. Is it a right way to go
There's no rule that says you cannot "extend" the data being returned from a REST API call. So instead of returning "just" the Order entity (as stored in the backend), you could of course return an OrderResponseDTO which includes all (revelant) fields of the Order entity - plus some from the Customer entity that might are relevant in your use case.
The data model for your REST API does not have to be an exact 1:1 match to your underlying database schema - it does give you the freedom to leave out some fields, or add some additional information that the consumers of your API will find helpful.
Great question, and any API design will tend to hit pragmatic reality at some point like this.
One option is to include a larger object graph for each resource (ie include the customer linked to each order) but use filter query parameters to allow users to specify what properties they require or don't require.
Personally I think that request parameters on a restful GET are fine for either search semantics when retrieving a list of resources, or filtering what is presented for each resource as in this case
Another option for your use case might be to look into a GraphQL approach.
How would you do it on the web?
You've got a web site, and that website serves documents about Customers, and documents about Orders. But your clients aren't happy, because its too much boring, mistake-prone work to aggregate information in the two kinds of documents.
Can we please have a document, they ask, with the boring work already done?
And so you generate a bunch of these new reports, and stick them on your web server, and create links to make it easier to navigate between related documents. TA-DA.
A "REST-API" is a facade that makes your information look and act like a web site. The fact that you are generating your representations from a database is an implementation details, deliberately hidden behind the "uniform interface".

Standard for RESful service with differing models?

From the perspective of an MVC developer, the Model should only contain Properties relevant to the view. So what is the best practice for dealing with this RESTful service scenario?
Usage 1
The RESTful endpoint "my-application/items/" is used to QUERY for a list of items which are bound to a paged list view of the items. It may contain many properties, such as ItemId, ItemName, CreatedDate, ModifiedDate, etc. It may even be a paged result of data from the server (eg 10 records out of 1000).
Usage 2
In a different area of the application, I need a select box for these items. In this scenario, I just need ItemId and ItemName. All other properties are irrelevant.
Do I...
...swallow my MVC pride and just use a single bloated model and a
single RESTful endpoint?
...create different RESTful endpoints with some sort of naming standard?
...do something else?
To me, this is not a theoretical REST issue. This is an implementation issue. Basically, you are asking whether you should implement a different endpoint for a separate use case or not. I agree with you when you say that the information exchanged with the client should be the minimum for performing a specific task. The only reason not to do so is convenience or budget.
In the use case 1, you should provide a wide set of data, in use case 2 you need far less of them..
Maybe use an endpoint as such .../items/details for the use case 1 and another endpoint .../items for the use case 2.
Maybe you could also implement a single endpoint and use a query parameter as such
.../items?detailed=true
Both solutions are perfectly acceptable.
The theoretical explanation behind this consideration is that REST asks the server to exchange resources' representation with the client. Representation means something similar to the view concept of the MVC model: it's not the entity itself, it's the most convenient way of describing it in a given context.
And this also means that different contexts may require different representations.

Representing multiple many-to-one relationships in REST

I am creating a RESTful API that contains the following resources shown in the following UML-ish diagram. As shown by the multiplicities (between parentheses), there are four one-to-many relationships.
I currently have the following GET methods defined:
GET /farmers
GET /farmers/[farmer_id]
GET /farms
GET /farms/[farm_id]
GET /llamas
GET /llamas/[llama_id]
GET /events
I am trying to decide what is the best and most RESTful way to access these relations, as well as accessing events related to Farms and Farmers (via Llamas). All of these relations will be made available using hypermedia links. The two options I have come up with so far are:
Multiple URIs
GET /farmers/[farmer_id]/farms
GET /farmers/[farmer_id]/llamas
GET /farmers/[farmer_id]/events
GET /farms/[farm_id]/farmer
GET /farms/[farm_id]/llamas
GET /farms/[farm_id]/events
GET /llamas/[llama_id]/farm
GET /llamas/[llama_id]/farmer
GET /llamas/[llama_id]/events
Single URIs and Filtering
GET /farms?farmer=[farmer_id]
GET /llamas?farmer=[farmer_id]
GET /events?farmer=[farmer_id]
GET /farmers/[farm_farmer_id]
GET /llamas?farm=[farm_id]
GET /events?farm=[farm_id]
GET /farms/[llama_farm_id]
GET /farmers/[llama_farmer_id]
GET /events?llama=[llama_id]
Are either of these methods preferred for REST, or can I just pick the one I like the most?
It really doesn't matter from a REST perspective, as long as you provide the links to the client.
From an implementation perspective, you may want to favor one of those options over the others if you're using a framework that uses a specific convention for automatic link relation publishing. For instance, Spring Data REST gives you the multiple URI scheme you defined above out of the box. Therefore, it would be a lot less work for you to simply go with that convention.
As Jonathon W says, it doesn't matter from a REST perspective. However, it does matter from a HTTP perspective.
From HTTP perspective, the multiple URI represents a unique, potentially-cachable resource. Cache control headers will obviously control any caching. However, Most proxies will not cache URIs with a query string, so the single URI with filtering option will generally not be cachable.
You also need to consider what are the consequences of not including the query string parameters. Ie. What would /events output? If the llama_id parameter is required, this is not evident.
Personally, I would go for the multiple URI option

Building REST web services with nested collections + collections inside entries

I would like to build a REST webservice that would provide :
nested collections,
collections inside entries.
Nesting collections would be used to refine a concept from general to particular, for example :
/vehicles/road_vehicles/cars/AB-123-CD
The idea is to limit the number of concepts appearing at the root of the webservice.
Collections inside entries would be used to access parts of the entries, for example :
/cars/AB-123-CD/engine/spark_plugs/1
could be a good URI for the first spark plug of the car whose id is "AB-123-CD". A nested collection makes sense whenever the deletion of the "container" means the deletion of all its parts.
DELETE /cars/AB-123-CD
would obviously delete :
/cars/AB-123-CD/engine/spark_plugs/1
and all other parts of the car (think of the car as being sent to scrap by the DELETE).
Question : while this kind of "clean URIs" are quite a common need, are there any software to simplify the building of such a webservice?
It seems that the Atom Publication Protocol (AtomPub) could have been a good candidate, since their vision of webservices if very close to what I want, but it doesn't seem to support nested collections.
The article The future of API design: The orchestration layer indicates Query-based APIs are putting the power in the hands of the requesting developer, although that power is limited. Using AtomPub along with query parameters is available to you in AtomPub build tools. I found some examples searching for "APIs Query-based" but could not find an actual definition.
https://developers.google.com/google-apps/contacts/v3/#retrieving_contacts_using_query_parameters
http://resources.arcgis.com/en/help/arcgis-rest-api/index.html#/Query_Related_Records_Map_Service_Dynamic_Layer/02r3000000nt000000/
Author goes on to say that Experienced-based APIs have device-specific wrappers but they are designed, implemented and owned by the device teams. Maybe the way to approach your issue is to create to different AtomPub end-points which present different views of the information?