I have a web service to retrieve the list of my users : /users
My User entity has a lot of attributes (with many relationship such as roles, address, etc) and it begins to be painful to retrieve the whole list.
I want to create a new web service to retrieve a list of a minimal User DTO. This DTO contains only the username, the first name and the last name.
What's your suggestions for this new URI ?
/users-minimal
/users/minimal
/users/func/get-minimal
... ?
If what's changing is merely the representation, you should make that available as a different media-type, not a different URI. For instance, if you have application/vnd.mycompany.user.v1+json for a normal user, you could use application/vnd.mycompany.user-minimal.v1+json for the minimal.
Now, you probably don't use custom media types like the above, and if you are asking about RESTful URIs, you're probably not using HATEOAS either. For those REST-like HTTP APIs, you should probably use a querystring parameter instead. Something like /users?minimal=1 or /users/?fields=username,first_name,last_name.
Related
I'm using Django Rest Framework and it's integrated with an external service. I'm using an endpoint to receive a callback from a webhook whenever a new task is created in the external service.
When the callback request comes in, my code needs to create at least one object. But it's possible that multiple objects will need to be created from multiple different models. For example, if a new task is created it's possible that it was created by a new user, in which I also need to create a new user object to reflect this.
In total, there could be up to 5 additional objects made as side effects. I'm aware of multiple different places that this logic could be added (e.g. service layers, serializers, models, managers, views). But there seem to be issues with all of these.
Has anyone dealt with this issue before? If so, how did you solve it?
First of all, it is important to understand the difference between an RPC-style API and a RESTful API. Simply put, you can imagine an RPC API to be "methods" that are "actions", while a RESTful API represents the state of your models.
For example, let's say we want to create an endpoint to handle user registration.
A RPC style endpoint might be /api/register. A register function that might do X number of things.
A REST style endpoint might be /api/users. Not an action, but simply just an endpoint that give us the state of the users that exist. A GET request would list the users and a POST request would create a new user.
With that said, it might be a bit more clear that in general, creating endpoints that do X number of actions might not be very "restful", and using a framework specifically named "Django REST Framework" might not be the right choice.
So in your particular case. I suggest that you avoid creating endpoints that work as methods, and instead treat them as the resources that they represent. This means that if you need to create a new user, you do a request to the user-endpoint, then if you need to create a new article with that user, you do a second request to the article-endpoint.
Using Signals for Side Effects
I think if you do want side effects, they should be managed using signals. For example, let's say that you want to send out emails using a contact form. Instead of having a /api/send_email endpoint, you instead do a /api/messages/ endpoint that represent a Message model, and then you use signals to send out emails whenever a new message is created.
By doing things this way, it still means that the API endpoint itself just represent the state of the model, while the side effect of modifying the state (sending a message on creation of a new message) is moved to the signal's responsibility.
What's happened to the ID fields for groups and videos? The Simple API does give you ID's but the new API isn't, though you do get a URL field with what looks like an ID in it.
Seems you only get a url field now? Can that be used as an alternative?
In the v3 API, the IDs have been removed and instead the unique thing for each item is the URI. You should be able to use the whole URI to uniquely identify the items, but the ID shouldn't need to be extracted from them and presents a list of potential pitfalls since that's an unsupported use case.
Depending on your use case, there are different approaches that make sense for this:
If it's for managing your local cache, you can use the URI safely to uniquely identify the response.
If it's for forming subsequent requests, you will likely find them already formed for you in the metadata key for the response (inside either connections or interactions).
For finding the URI from a Vimeo video, we now include the URI inside the oEmbed response.
For the last few days I’ve been looking into the world of REST frameworks (the Django rest framework in specific).
The concept of a RESTful API seems pretty straight forward but there is one thing I’ve been wondering about.
Let say I have the following data structure:
Group
ID
GroupName
User
ID
UserName
GroupUser
userId
groupId
When working with dependent resources I’ve been wondering how you would return and create these objects.
In the case described above I can think of two ways to create a user and add the user to one or more groups:
Option 1:
I send a POST request with the UserName to the server.
Followed by one or multiple POST request adding the user to one or more groups. Adding non existing groups in separate POST requests.
Or, options 2:
I create the user and add all the groups in the request and let my serialiser take care of any of the groups that have not been created yet.
The second option sounds more efficient but request can probably start looking rather strange since some of the groups will be defined by an ID (know groups) and some by a name (non-existing groups). The main thing with this solution is that the serialisers will be rather different from the models.
My question basically boils down to the following:
In a RESTful API how should you deal with dependent resources?
It becomes pretty obvious if you try naming the things.
Option one would be something like:
// creating the user
POST /user
// adding users to the group
POST /usergroup
POST /usergroup
// adding a new group
POST /group
POST /usergroup
Option two would be more like:
POST /CreateUserAndGroupMappingCreatingMissingGroups
Option two is a RPC model, not a restful model.
REST is about nouns: if you can't name the thing you are posting to, or if that thing looks like a verb, then you haven't built a very restful service.
There is nothing wrong with a RPC service; just be aware of what you are creating.
I get the simple Restful design following one type of object:
GET /users
GET /users/123
POST /users/new
POST /users/1/edit (or PUT)
POST /users/1/delete (or DELETE)
...
Follow a Relationship from a type of object to another:
GET /user/123/company
GET /user/123/roles
POST /user/123/roles/new
…
What about a composite DTO mixing multiple objects in it? For example:
//Listing all users with their companies and primary role
GET /usersWithCompaniesAndPrimaryRoles
//List all companies with users and roles count in each company
GET /companiesWithUsersAndRolesCount
In this case, my API link doesn’t look very clean or Restful to me anymore? I am wondering how I should structure the CRUD of these composite DTOs in a Restful way? Please advise me, or link me to where I can learn how to do that?
Thank you very much.
A Restful design should have such API paths.
Instead, you should use the GET /users URI, and provide query parameters. for example:
GET /users?with_companies=yes
In the Restful, you should not think about URIs as API commands. Try, instead to think about URIs as entities, that you can Get, Insert, change, and delete.
There is no room for other "commands".
That is why, for example,
There shouldn't be POST /users/new API path.
instead, just post to /users.
Another possible RESTfull way is to create a "Query Resource" object using POST, returning "Query Resource ID Number", which will later be used in a separated GET request.
By that you are creating saved queries which can also be efficient for re-querying as well.
I have perused the questions asked about this, but I still don't have a definitive answer.
I have an application and would like to build a RESTful API to expose a subset of information. I have three resources:
users
reports
photos
Users have reports and reports have photos. Photos cannot exist outside of reports and reports cannot exist outside of users.
I have designed the following URLs for my requirements
User login, server responds with token which is sent in the header of all API calls
GET example.com/api/
Get user info
GET example.com/api/users/{username}
Get all user reports
GET example.com/api/users/{username}/reports
Get all photos of a report
GET example.com/api/users/{username}/reports/{report_id}/photos
Add a photo
POST example.com/api/users/{username}/reports/{report_id}/photos
Delete a photo
DELETE example.com/api/users/{username}/reports/{report_id}/photos/{photo_id}
Modify photo description
PUT example.com/api/users/{username}/reports/{report_id}/photos/{photo_id}
Questions
Is it good practice to add a resource id in the URL, i.e. resource/id, or should this rather be added as a query parameter?
Is this method of chaining resources, i.e. resource/id/sub-resource/id/etc., acceptable and good or should I put all my resources at the top level and specify its position with query parameters?
Nothing wrong in this design.But this creates long URL which sometime are difficult to understand and the user of the API needs to know the hierarchy.Moreover the consumer of the API need to write more code in little bit non-standard way(Even though it can be done, but will be little messy). Think this from a different perspective
You have three resources and each has its own identity.So if we refactor the above URI's it will looks like below (I am demonstrating only GET)
User Resource:
Get users list
GET example.com/api/users
Get specific user
GET example.com/api/users/{username}
Report Resource:
Get all reports
GET example.com/api/reports
Get a specific report
GET example.com/api/reports/{report_id}
Photo Resources
All Photos
GET example.com/api/photos
Specific Photo
GET example.com/api/photos/{photo_id}
User All Reports
GET example.com/api/reports?username={userName}
Specific report of a user
GET example.com/api/report?username={userName}&report_id={reportId}
User All Photos
GET example.com/api/photos?username={userName}
User All Photos for a report id (You may not need user Name if report_id is unique irrespective of the user, which will further simplify the URI)
GET example.com/api/photos?username={userName}&report_id={reportId}
All photos of a report
GET example.com/api/photos?report_id={reportId}
This simplifies the understanding and more standard code can be written on the consumer side using this approach.
IMHO you are modelling it well.
Regarding 1 I'd rather go with resource/id rather than query param. But one thing you must have in mind when modelling is the cache mechanism by proxy and so on. So do not forget the headers.
I go for query params for filtering and those sorts.
About the login, the credentials should be in the headers, and no specific resource is needed. Just apply per resource security.
I don't see anything wrong with your scheme.
Most frameworks nowadays use a similar standard for specifying url's (like Django).
In my personal opinion, it makes the URL more readable and a bit nicer for the user.