REST conventions for a friends list - rest

I have a database (ORM) with users which look like this:
UserEntity (
id: UUID,
name: String,
phoneNumber: String,
friends: List<UserEntity>
)
I also have the following friends endpoints:
GET /user/<userId>/friends (returns a list of UUID's for all friends the user has)
POST /user/<userId>/friends?friendId=<friendId> (saves a new friend to the friends list)
DELETE /user/<userId>/friends?friendId=<friendId> (deletes a friend from the friends list)
Now I asked myself: is this the correct way of implementing a RESTful friend list and what is a good REST convention to obtain the profile of a friend. Should the friend resource be reached from the following path:
GET /user/<userId>/friends/<friendId>
Or from this path:
GET /user/<friendId>
Both of the given endpoints from above give back the same resource (a profile) but which one should I choose? I am diving deeper into REST conventions but I didn't find any clear answer for this. I dont't even know if my current REST design is correct. Thanks in advance for your help.

What you are talking about I would call nice URL convention. https://en.wikipedia.org/wiki/Clean_URL It has nothing to do with REST https://www.ics.uci.edu/~fielding/pubs/dissertation/fielding_dissertation.pdf and I have no idea why people think it has. From the REST point of view it would be equally good to do something like GET|PUT|DELETE /dsgvs23w?x235rwef=1&aegs234523f=2 and decide which URL to follow based on the metadata that describes it. If you violate HATEOAS, then you don't have a REST API.
As of the nice URL convention I would do something like GET /friendships/?user=1 and GET|PUT|DELETE /friendships/1+2 and add some extra info about the friendship e.g. strength=BFF, duration=20y, etc. But there are infinite good solutions for this and it really depends on your needs.

Related

Sub-collections in REST api

How many sub-collections can have a resource?
Just imagine that we have this model:
accounts -> posts -> comments
Everything is clear for accounts-posts pair.
/accounts/{account_id}/posts/{post_id}
But what about comments? What is a proper way to point to a single comment?
/posts/{post_id}/comments/{comment_id}
or
/accounts/{account_id}/posts/{post_id}/comments/{comment_id}
or (direct pointing)
comments/{comment_id}
The general rule of thumb is to only go one layer of subresources deep. An account may have many posts like you show, and a post may have many comments, but since the post id is unique, including the account id is a bit redundant when trying to get the comments for a post.
/accounts/:account_id/posts
/posts/:post_id/comments
Ruby On Rails also lists this in their docs (just for a bit of a citation). https://guides.rubyonrails.org/routing.html#limits-to-nesting
Additionally, if you already have the id of a resource you don’t need to nest it. As short of a route that gets the job done is preferred.
/comments/:id

REST api best practice

I create rest api and I have a POST which has many comments. What is the better url to get post comments
//Get all comments of a post
GET /posts/{postId}/comments
or
GET /comments/{postId}
//Create new comment
POST /posts/{postId}/comments
or
POST /comments/{postId}
A POST has many CATERORY and a CATEGORY can belong to many POST
How I can create a post with ,for example, 3 categories. And how I can connect a specific existing post to a specific existing category
What is the better url to get post comments
REST doesn't care about your spelling conventions for URI -- that's part of the point. So you should use whatever spellings are consistent with your local conventions.
Depending on your API and representations, it may be useful to think about relative references in your hierarchy. For instance, if your base URI is /posts/{postId}/abstract, then the relative reference ../comments can be resolved to /posts/{postId}/comments; but there is no analogous trick to get you from /abstracts/{postId} to /comments/{postId}.
How I can create a post with ,for example, 3 categories
how I can connect a specific existing post to a specific existing category
How would you do it with a web site? Having done that, how would you make the web site machine readable?

How specific does an API's routing need to be?

I'm creating an API, I have a user that I can request by calling:
/api/request/user/{id}
This works fine.
Say each user had a set of skills, could be one skill or 100.
I want to get all the skills for a specific user.
Would I be super specific and make it so that you'll have to call:
/api/request/user/{id}/skills
Or does this:
/api/request/skills/{id} (where {id} is the user's id)
suffice?
Is there a REST API standard I should be following or is it flexible ?
Any advice is highly appreciated, Thank you.
As skills is user's property, let's consider it as sub-resource. Getting sub-resources is based on nesting URL (hierarchical way), so /api/request/user/{id}/skills would be great!
In /api/request/skills/{id} case id should be an identifier of skill to make your API intuitive.
Also remember about naming convention. Be consistent, your skills resource is plural so let's rename user to users.
So, to sum up
/api/request/users/{user_id}
/api/request/users/{user_id}/skills
/api/request/skills/{skill_id}
would be nice.

Proper way to structure my REST api in this case

I am trying to build a little web application with the MEAN stack (MongoDB, ExpressJS, AngularJS and NodeJS).
My question is very simple. If you take the example of a blog, it will contains blog posts, that you could list at this url:
GET /api/posts
You could also get the comments for that posts:
GET /api/posts/:postId/comments
and get a single comment:
GET /api/posts/:postId/comments/:commentId
The relation between post and comment is really obvious here, but does it still makes it mandatory to have it this way? or could I just perform my CRUD operations through /api/comments? In the end, a comment object in mongodb will always have a postId attribute anyway which will reference the post that it is related to... Moreover, the API will not be exposed and is strictly meant to be used by the application.
does it still makes it mandatory to have it this way?
No. This is not mandatory at all.
or could I just perform my CRUD operations through /api/comments?
Yes. This will result in cleaner resources URIs (endpoints).
You can also get post-specific comments with:
GET /api/comments?postId={postId}
Further, you could also drop the /api prefix if you are serving only an API at the given host.

Rest API, relationships and subsets

I have some questions about Rest API and relationships.
I know the questions of relationship is always tricky with Rest.
I have some users, posts (created by user), relationships between users (imported from fb), interactions on posts (created by user) and users can like a post.
User can create a posts which will be seen only by others users who have a relationship (up to 2 jump, like friends of friends) with the poster and then can create interactions on the post.
We do a filtering on the backend based on your authentification and just do the magic on /posts which will return you the list of post that you can see.
It feel a bit funky to me because it make the same endpoint (/posts) will return different set of data based on the current user. We could of course pass a parameters (?viewable_by_user_id=:id) to reflect it a bit more, but I wonder if I can do anything to improving caching.
I'm thinking of improving our API to a v2 with this endpoints:
GET/PATCH/DELETE /users/:id
POST [post] /posts: create a post (using current auth user as the owner of the post)
or
POST [post] /users/:id/posts: create a post for this user
GET /users/:id/posts : get posts created by the user
GET /users/:id/stream : get posts "viewable" by the user (this is the one I'm strugeling with)
or
GET /posts?viewable_by_user=:id
GET /users/:id/like : get posts liked by the user
POST [post_id] /users/:id/like : like a post
POST [interaction] /posts/:id/interactions : create an interaction on the post for the current user
GET /posts/:id/interactions : get post's interactions
GET/PATCH/DELETE /interactions/:id
Any thoughts on how I could make the path reflect a bit more the relationship?
I've thinking on creating an endpoint for relationships but seem a bit to complex to maintain (users don't create relationship manually, we pull them from fb)
Thank you for any feedback, and let me know if my question is too ambiguous or irrelevant.
What if you think of it as this: (Note that I just like putting "posts" first since it tells what and then the restrictions go to the right of that. You may like the other order.)
GET /users/posts/<viewer>/<creator>
This gives some degenerate cases:
GET /users/posts/<me>/<me>
to get all the posts I have created
GET /users/posts/<me>
to get all the post from all other users
GET /users/posts/<me>/<stranger>
would return nothing because I am not allowed to see the stranger's posts
GET /users/posts/<me>/<friend>
would return the posts from my friend.
NOTE: In all cases, all posts returned are those allowed to be seen