Context
I have to create a RESTFul API which deal with :
Books
Category of books
The application is splitted like this :
Each client has an API key
Each user of a client can manage (get/post/put/delete) multiple books / categories of books related to the client he is linked to.
Following the REST principle, only the person that creates the ressource, "the ressource owner" can manage this ressource.
First problem
However, in this context, it's possible for a user to share a book to another user related to his ecosystem, meaning that he cans share informations only with the users that share the same API key (the same client).
Does it mean that I have to manage an owner_list in my book object ?
Second problem
I told in the before explanations that I have API keys corresponding to a certain client. Should I have a client_id stored in my user object ? Permitting me to quickly know and share informations between users corresponding to this client_id ?
Third problem
Admitting that I want to work with REST Hateoas, in a Java context. Looking at how hateoas work, it seems that I have to create a specific object that permit me to hyperlink my ressources, like (in JSON) : {hateoas:{key:"user", link:"/users/1234"}} ? Or does it exist something better ?
Last problem
Admitting that I want to work with microservices architecture, and that I have :
A user microservice (for authentication)
A book microservice
I know that I should send informations through AMQP protocol when I need an information from a different microservice.
So :
What kind of exchange / queue (topic, fanout etc...) should I use ?
What kind of information should I send over the network ? Because, okay, I know where the ressource is, with hateoas, but what should I put inside the "tunnel" to have a response ?
Related
For exmaple: We have a REST API which provides data for multiple consumers. The most case is like: Frontend (accessable for everyone), admin/management (for admins only), mobile app.
These ones differs in the response data which the REST API delivers. For example, in the admin request, the API should respond the email of the user. In the frontend not. Or the mobile app, shouldnt receive unnecessary data, which are not displayed in the views.
My idea was to set adapters in front of the REST API, but this won't work, if you don't have multiple domains available (e.g. api.xyz.com, api-manage.xyz.com).
I think this is a common way, which most of the app needs. I don't want to build multiple APIs to cover this case.
Is there any way on the application side, for example with middleware? Or I know there is a role based approach, but I dont think, this is enought abstract, because the role doesnt decide which device it is.
There is a little solution:
Role based decision which fields the user can be retrieve. Additionally the consumer has to put a header, or a queryparam like "frontend", "admin", "mobile", to identify which data will be returned. This is independent of the "which the user is able". It's just for optimization.
Are there any other solutions?
Your API should not know about your clients but it should offer the possibility for the clients to do what they want/need. Let's say you need to display a list of product with details. On the desktop you might bring 100 products but in mobile only 10. So the api need to provide a configurable paging. Also in the desktop you might get more information than on mobile. So here if you have an entity product, in the desktop you will get all the fields( multiple attributes for example) but for the mobile you get only the name and one attribute (for example the price) to minimize the payload size.
So the API need to be generic but give clients possibility to use it based on their needs.
For example: We have a User model, which in turn has several Company entities. I see 2 solutions:
1) Classical. Make an API like:
/users/
/users/3/
/users/3/companies/
and issue /users or companies request separately. However, if we need to have both user and his/her companies information in one view (on Angular2) - we need to send 2 requests to the server.
2) Put the related/nested data inside the level-1 object model. In request:
/users/3/
the server will provide information about the User, together with his Companies. In this case we get all information for 1 request. But again, the company has an unlimited number of Storage entities. What if they are required in one separate view?
I'm more inclined to the first option, but I'm confused by the description of the REST style: "The view must fully represent the resource." Satisfaction of this requirement can lead to a partition of the resource into child resources and, accordingly, to smaller representations. "
Please, help with advice, I doubt in connection with the lack of experience what decision will be correct in this case. Oh yes, I forgot, Backend on Django (Python) using Django-Rest-Framework - All this is a SaaS for ~ 1000 users.
Approach 1 is an an ideal approach for REST. But when it comes to designing APIs for the displaying information on the UI it involves much more than just partitioning the APIs as per resources.
So I would suggest including the Company information in the User API. But as you suggested Company object can have very large list of Storage objects, in this case I would recommend including only the necessary and sufficient fields of Company model into User API. So that you will be able to render one view. And then later when user expands the Company section then you can pull the left-over fields from /company/<id> API.
This way you will have lesser API calls for the hits where user doesn't look for Company details and your API will be light weight as well.
Context
I m actually developping a simple application in which I need to use REST level 3 HATEOAS.
I m having two entities :
User
Billing
I need, when I add a billing, to reference the user inside of it.
Questions
What are the informations I should send to my backend, from my frontend app, to add the hateoas reference, inside the billing ressource, concerning the user ?
I mean, inside the body of the request, should I send the url of the user ressource ? Or should I send the id of the user, and then making an url discovering to get the real user url ?
Context
I m having two microservices :
User that manages users (crud operations)
Billing that manages billing informations, with a reference to a user
Actually, for me (tell if I m wrong) it's a good idea to store user informations into billing data using hateoas. So we can "walk through it" with an hyperlink in the response of the API right ?
We could obtain something like :
billing:{
// some informations
_links:{
owner:"http://80.80.80.80:7000/users/123456789"
}
}
Questions
How should I do, to create a new billing ? In fact, when somebody post a new billing on the microservice, he sends the user too. Does it mean that I need to have a UserEntity in my Billing service AND my User Service ? So the billing service will be able to marshall the request, meaning code duplication between the two services ? Or should I do something else ?
Then, is this the role of the front end (API consumer) to make 2 requests (one for billing, and one for the user related to the billing) to get the ressource ? Or should the BillingService get the User before responding to the front ?
I have seen in an article, that it's a good thing to use amqp / bus when dealing with microservice, to know if a ressource exists, or to check if it exists. Now we need a service container/registry to dynamically discover other services. In my case I use Zookeeper. But how can I do to tell Zookeeper "give me the location of the service(s) related to the ressource with hateoas links : http://80.80.80.80:7000/users/123456789" ? Am I missing an important information in my hateoas schema ?
How should I do, to create a new billing ? In fact, when somebody post
a new billing on the microservice, he sends the user too. Does it mean
that I need to have a UserEntity in my Billing service AND my User
Service ? So the billing service will be able to marshall the request,
meaning code duplication between the two services ? Or should I do
something else ?
The user that the billing service need is not the same one in the user service. Usually, the user's identity is all the consumer need to post a new billing. If the billing service need more information of the user, it may query from the user service. There may be some code duplicates here, but the code plays different roles in each service which means they can evolve without disrupting each other. Some questions may explain further here: Bounded contexts sharing a same aggregate, Handling duplication of domain logic using DDD and CQRS
Then, is this the role of the front end (API consumer) to make 2
requests (one for billing, and one for the user related to the
billing) to get the ressource ? Or should the BillingService get the
User before responding to the front ?
I think it brings the most flexibility to let API consumer navigate the links. What if the consumer is not interested in the owner detail?
I have seen in an article, that it's a good thing to use amqp / bus
when dealing with microservice, to know if a ressource exists, or to
check if it exists. Now we need a service container/registry to
dynamically discover other services. In my case I use Zookeeper. But
how can I do to tell Zookeeper "give me the location of the service(s)
related to the ressource with hateoas links :
http://80.80.80.80:7000/users/123456789" ? Am I missing an important
information in my hateoas schema ?
Not quite understand this one. If the consumer has the link like "http://80.80.80.80:7000/users/123456789" already, it can access the resource directly. Why should it ask the zookeeper? I think the zookeeper helps the billing service assemble the URI for owner. For example, the billing service tell the zookeeper "Give me the location of the service related to user resource".
Another solution would be that you store all the necessary information in both services. E.g., if you need data of the user within a billing, then just store all the data in the billings datastorage as well. The sync between both services you would do through a queue ( subscribe / publish ). This comes with pros and cons but in the end you end up having one synchronous http call, if you want receive the data for a specific billing.
We have 2 developers who have conflicts in the way to design the RESTful API Endpoint. Basically, let say that we have Facebook product in hand, one table for the posts.
First developer give the opinions that
We should seperate Endpoint by product, not by the technical storage. To be like that, we will have endpoint for user facebook post and other facebook post.
/v1/wall/mypost
/v1/wall/other
To be like that, we be able to configure each products that may return difference results
Second developer disagree, give the opinions that
If be like that, it will make infinite endpoint. it will have /wall/someone, /wall/sometwo.
We should have single endpoint, and just let that be a part of query. ex. /wall?user=someone, /wall?user=sometwo
The endpoint should be look like technical schema, it return the same result, why it have to seperated to make it more jobs on maintenance the code.
What is the good practice to design our endpoint? Is it should be endpoint by the product? or is it should be by schema?
It should depend on what 'resource' that the service is suppose to manage from the API user perspective and not from the internal implementation.
With that, if the service is to manage say, a resource that can be identified by 'someone', 'sometwo' and, then the correct way to model it is
/wall/someone/
/wall/sometwo/
In this case, 'someone' and 'sometwo' are two different resources and you could have infinite # of them; but that has nothing to do with the internal storage or implementation.
On the backend, there should be some url pattern to extract 'someone' and 'sometwo' as resource and map them into internal implementation details.
What are these "endpoints" you speak of? That's SOAP terminology! RESTful web services are defined in terms of "resources" that are uniquely identified by URL.
A resource typically represents an entity in your domain model (e.g., a user). The ID of the entity is typically used as a path element ("path parameter" in the lingo of most REST libraries, such as JAX-RS) in the URL. Query parameters should only be used to sort/filter results on the server side.
Your first developer is closer to being correct.