I'm creating a REST API in Laravel and there is one thing I can't figure out. The situation is as follows; a user can log in, browse articles and make them a favorite.
The favorite table consists out of article_id and user_id
The requests are designed in the following way:
[GET] /article/24 view article 24
[GET] /article/24/favorite indicates a favorite, if not return 404
[POST] /article/24/favorite make favorite
[DELETE] /article/24/favorite remove favorite
Seems fine, but the nested resources by default expect the following format:
/controller/[id]/sub_controller/[sub_id]
What's the best way to avoid this sub id requirement? I don't need the ID of the favorite because the combination of article id and user id are enough to locate the item in my database.
These are my current routes for the requests:
Route::resource('articles', 'ArticlesController',
array('only' => array('index','store','show','destroy')));
Route::resource('articles.favorite', 'ArticlesFavoriteController',
array('only' => array('show','store','destroy')));
Currently, I require the API user to append /0 to the url in order to trigger the right route, but there must be a better way.
I think you should consider not using Laravel's ResourceController here. Maybe you should go with RestfullControllers for your specific needs.
Related
My data model is like this:
User: id, email, hashed_password
Item: id, name, color
UserItem: user_id, item_id, rating
and I want to write a RESTful API to get these resources. The authentication is provided via OAuth 2 with a JWT token (that contains the logged user id).
First approach
Endpoints
The first idea for a URL structure is (the one I chose when there was still no authentication):
/items/{item_id}
/users/{user_id}
/users/{user_id}/items/{item_id}
In this case a user with id 1 could use:
GET /users/1 to get their own information;
GET /users/1/items to get their own items (with rating);
GET /items to get all items that they could add to their collection.
Analysis
I think this solution is quite clear, but also unelegant.
Good:
You can easily get other users info (if they are available to them);
1-to-1 relations between endpoints and data models.
Bad:
Longer URLs;
There is redundancy (why GET /users/1/items when in the token you already have the information about id 1?).
Second approach
Endpoints
Given that you can extract the user id from the token, the structure could as well be more simple:
/items/{item_id}
/users/{user_id}
In this case a user with id 1 could use:
GET /users/me to get their own information;
GET /items?class=owned to get their own items (with rating);
GET /items?class=all to get all items that they could add to their collection.
Analysis
This solution is a bit messy but probably more elegant.
Good:
Shorter URLs;
Less redundancy (GET /items to get your own items).
Bad:
Only model UserItem is represented (even though in this case it is probably almost meaningless to get an Item without its rating, that could be set to null if the user has not yet added it);
Not straightforward to get other users' items (maybe something like GET /items?user=3?).
Conclusions
Honestly I don't know what is the best practice in this case. I feel like there is something off about both of these. Maybe there is an hybrid approach I'm not seeing?
How would you organize a model like this?
You could look into a format like HAL. HAL gives you a way to describe specific resources (items) and allows you to create multiple collections that point to those resources.
This means that individual items could be hosted at /items/xyz, but items can be both part of the /user/a/items and /items collections.
I put a lot of work into a hypermedia client: https://github.com/badgateway/ketting . This is not just an ad though, there's alternatives but that approach of API design might we well-suited for you.
But regardless of the client you're using, systems like this can avoid the issue of retrieving the same item through multiple endpoints. A single item has a canonical url, and if the system is designed well you only have to retrieve an item once.
A collection is just a list of links to the resources (items) that belong to that collection. They point to the item, but don't 'contain it', just like a regular hyperlink.
I wonder what saying good practices create REST API. Should or not I create URI which will allow get e.g. several specific users?
For example I mean:
/usermanagement/users/{j_goldman,wafik,morder}
And this uri will be returns 3 objects users for j_goldman, wafik and morder.
You can do this but it won't be restful IMHO. If you really need to do this you should think about remodeling your resource selections say, all three users you want to get belong to a particular group with id 111. Then you can do something like /groups/111 GET. If you cannot then I guess you should stick with restful solution and use three API calls to get users separately.
What you are doing is searching for a specific set of users. With a query parameter within your URL, you can achieve this.
To return a single user (id is 5):
/usermanagement/users/5
To return all users:
/usermanagement/users
To return a set of users based on search:
/usermanagement/users?username=
That way, your API is open to searching by a specified criteria which can also be extended.
Say, you wish to search by location:
/usermanagement/users?location=
Say, you wish to combine these:
/usermanagement/users?username={criteria}&location={criteria}
You may also want to expose a search endpoint itself:
/usermanagement/search
You might find other options here too:
RESTful URL design for search
I'm tring to create a little registration app, that will be published as a REST API. It will allow users / systems to create an account on my system. They will pass in a username and a password.
According to the rules that i've read, the "/" in a URI must be used to indicate a hierarchical relationship.
So I'm wondering if this type of a URI follows the rules, and is intuitive enough:
POST http://myregistrations.com/users/user/{user_id},{password}
GET http://myregistrations.com/users/user/{user_id}
PUT http://myregistrations.com/users/user/{user_id},{password}
DELETE http://myregistrations.com/users/user/{user_id}
or should i remove the "users" part from the URI? In that case, if I want to get "all" users, i could just do the following:
GET http://myregistrations.com/user/
DELETE http://myregistrations.com/user/ ** i might not allow this but just for discussion purposes...
And the rest of the methods would look like this:
POST http://myregistrations.com/user/{user_id},{password}
GET http://myregistrations.com/user/{user_id}
PUT http://myregistrations.com/user/{user_id},{password}
DELETE http://myregistrations.com/user/{user_id}
I don't want to over complicate things... but I also want to make sure I follow conventions.
I am leaning towards the second example, where I don't have "users". Given that each part of the URI should map to an addressable resource, and that I won't be allowing batch updates to accounts, having a concept of "users" seems useless at this time. I might be missing something though.
Maybe I'm just splitting hairs. I've been reading other posts here too about defining REST APIs... but I haven't found anything yet.
Thanks.
You can have both concepts (user and users) with a single API. The URI /users/user seems convoluted to me.
Over-simplified example:
Post one user:
POST /user/{user_id,password}
Post multiple users:
POST /user/[{user_id,password},{user_id,password}]
Get one user:
GET /user/{user_id}
Response: {user_name} or [{user_name}]
Get multiple users:
GET /user/{search_user_name}
Response: [{user_name},{user_name},{user_name}]
Typically plural is how you reference a resource so users in this case and not user. This is what you're routes should look like to follow the REST pattern.
POST http://myregistrations.com/users/ --> The post payload should contain: {user_id},{password}
GET http://myregistrations.com/users/{user_id} --> The user_id is in the URL
PUT http://myregistrations.com/users/{user_id} --> The user_id is in the URL
DELETE http://myregistrations.com/users/{user_id} --> The user_id is in the url
I don't want to over complicate things...
I have bad news for you, you've already overcomplicated things. The REST clients know nothing about the URI structure, because they follow hyperlinks annotated with semantic metadata. The clients check this metadata instead of the URI structure.
My data structure is fairly simple but I am getting a little confused with how to structure my Web API controllers and routes.
In my data structure a City has a list of Venues and each venue has a list of Events.
This brings me on to the URL routes of the application. Do I have
Option 1
/api/cities/{id} and /api/venues/{id} and /api/events/{id}
But how would that work when POSTing a venue (to a city) or an event (to a venue)?
Option 2
/api/cities/{id} and /api/cities/{cityId}/venues/{id} and /api/cities/{cityId}/venues/{venueId}/events/{id}
Which sort of makes sense because the first call I need to make when using the API is to list all the venues given the city.
Finally am I right in thinking that my API controllers will effectively be getting, upserting and deleting only City documents but will be serving more specific data sets to the client?
I usually favor the second options but that requires either attribute routing package or ASP.NET Web API 2 (not released yet).
First option is also valid as an easier approach, as long as your venue object contains a cityId or event object cotains a venueId.
I am designing a REST API for inserting a record to the "solutions" table. A "solution" has a solverID, problemID. I have two different designs in mind:
POST /solutions
and passing the solverID and problemID in JSON with the content of the solution. Or putting the solverID and problemID in the URI:
POST /users/:solver_id/problems/:problem_id/solutions
Which design is better?
It's a good practice to define your resources in a consistent hierarchy, so that they are easily understandable and predictable.
Let's say this is the URL to retrieve a question -
GET /users/{solverId}/problems/{problemId}
It clearly conveys that the problem belongs to the {solverId}.
The following URL would clearly show that the we are retrieving all solutions for problems solved by {solverId}
GET /users/{solverId}/problems/{problemId}/solutions
To create a new solution for the {problemId}, you would do a post on
POST /users/{solverId}/problems/{problemId}/solutions
To retrieve a particular solution you would do a get on
GET /users/{solverId}/problems/{problemId}/solutions/{solutionId}
When to use Ids in path vs query ?
If an ID is definitely required to identify a resource, use it in the path. In the above scenario, since all three Ids are required to uniquely identify a solution, all of them should be in the path.
Let's say you want to retrieve a solution that was given in a particular date range, you would use the following
GET /users/{solverId}/problems/{problemId}/solutions?startDate={}&endDate={}
Here startDate and endDate cannot uniquely identify a resource, they are just parameters that are being used to filter the results.
Go with the first one. I would keep your urls as clean and simple as you can. Here are some other examples off the top my head. Not sure on your entire structure.
POST /solutions
GET /solutions?solverid=123 //query solutions by user
GET /users/555/problems // problems for a given user
GET /users/555/solutions // solutions for a given user
GET /problems/987/solutions // solutions for a given problem
I came up with a scheme: including user ID in the route only when authentication is not needed for the route, otherwise, the user ID can be figured out from the authentication information, and the above route becomes:
POST /problems/:problem_id/solutions