Which Endpoint should represent a trhreeway many to many Relationship with non related elements as well - rest

It's difficult to sintetize the question into one line, but I hope I can explain myself better here:
I've got the following model:
Users
id
Messages
id
Tags
id
UsersMessagesCategories
id
userId
messageId
tagId
Tags are NOT created by the user, available tags are created via admin panel.
I want to make an endpoint that returns the avaliable tags for a message but with the ones that are already associated, by that user, to that message flagged.
I can't seem to find a Rest standard way to make this.
PS: Just to make it clear, I want:
{
tags:[
{id: 1, associated: false},
{id: 2, associated: true},
{id: 3, associated: false}
]
}
Or maybe the way is:
{
tags:[
associated:[
{id: 2},
{id: 1}
],
unassociated: [
{id: 3}
]
]
}
I also don't know if it should be returned by (I guess this is the one):
/users/1/messages/1/tags
or by:
/tags
or even by:
messages/1/tags
Edit: Changed the endpoints so the URI is built with plural names.

Why don't you try with something like /tags?user=X&message=Y? As I understood tags are not direct children of messages or users, so no need to be direct children in the URL pattern.
REST doesn't define a real pattern to access resources, so you can use it more query-like with GET parameters like I wrote or you can have a more tree-like structure as you proposed.
The best thing you can do is to make every REST resource of your project accessible via a similar URL pattern, to make it more user friendly.
The first solution you proposed to format in JSON the results is the better one in my opinion
{
tags:
[
{id: 1, associated: false},
{id: 2, associated: true},
{id: 3, associated: false}
]
}
but also this depends a lot on how you modeled the others REST services of your project. If you want you can return also the user which associate the tag with the message to improve readability.

You could go for (mind the plural names):
/users/:user-id/messages/:message-id/tags
Assuming a tag can exist without a message, you also could support an endpoint to return all the available tags:
/tags

Related

Is it normal to have regular model for GET and "flat" model for POST from Design REST point of view?

The questions about possibility to have different models for POST and GET methods in REST api have been asked several times but I would like to clarify one specific moment.
Suppose we are designing api about sport competition.
Models and corresponding resources:
1) Player
{ "id" : 2,
"firstName" : "Nikolay",
"lastName": "Grigoryan",
.....
}
/players/2
2) Tournament
{ "id" 1,
"name": "Some tournament",
"date" "01.02.2019",
.......
}
/tournaments/1
3) Participant
{
"id": 2,
"tournament": { "id" 1,
"name": "Some tournament",
"date" "01.02.2019",
.......
},
"player": { "id" : 2,
"firstName" : "Nikolay",
"lastName": "Grigoryan",
.....
}
}
/tournament/1/participants/2
When I'm requesting the participants of the certain tournament it's convinient enough to have a separate field by name player containg full nested Player model whith all available fields. But when I'm creating a new participant the situation looks different for me. I would prefer to have just playerId to provide as POST body:
/tournament/1/participants
POST
{
....,
playerId: 2,
.....
}
but not
{
....,
"player": {
"id": 2,
....
}
}
It seems no need to have nested model here but instead only playerId is enough and by this reason no need to have nested object only for holding id at all.
Is it ok to have such simplification of model for POST request or they should be of the same structure? Probably I miss something important by doing such conclusion. If so I would be grateful for explanation what exactly it is.
Thanks in advance.
Is it ok to have such simplification of model for POST request or they should be of the same structure? Probably I miss something important by doing such conclusion. If so I would be grateful for explanation what exactly it is.
How would you do this as a web site?
You'd probably have some sort of form, with a drop down control that lists the identifiers that you might use. The client would choose the identifier from the list, and submit the form. The result would be an HTTP request message with the identifier in the request body.
One approach to at least take inspiration of is to look at HAL.
If a tournament has players, and this is a many-to-many relation it might make sense for players to be associated to a tournament via a link.
To get a list of players, you would simply embed the player resources.
To identify players, you don't use their id, you use their url.
To associate players to a tournament, you could update the links.
As an aside I think that having models that are identical for both receiving (GET) and sending (POST) is a very nice property and makes things easier to understand, but it's also completely fine to abandon this rule where appropriate. I find that especially the situation where people often need a different approach is the case where multiple resources / models are associated with each other. There's not one elegant way to solve this, but using links instead of id's might give you some tools to solve this in a general manner that is applicable everywhere.

RESTful API design - how to handle foreign keys?

I'm designing a RESTful API and I'm trying to figure out how to show and update foreign keys for resources.
Let's I have an object User and it has an id, name and a foreign key (many-to-one relation) to entity: Computer.
What I see in most of the examples online:
GET /users/1
{
id: 1,
name: "Bob",
computer: "<url>/computers/5"
}
Which I can understand, it's a link to another resource. But what do you do when you want to pick another computer for bob?
PUT /users/1
{
name: "Bob",
computer: "<url>/computers/4"
}
This feels really weird.
I'm also thinking about the following case: Say the person that has to implement the API can choose a computer for Bob using a dropdown and the current one should be selected, I'd need the id to do that. Do I have to parse the url myself to chop off the id?
Is there a reason why I should not just do:
GET /users/1
{
id: 1,
name: "Bob",
computerId: 5
}
PUT /users/1
{
name: "Bob",
computerId: 4
}
I would be tempted to formalise the HATEOAS a little here and have:
GET /users/1
{
links: [
{ rel: "computer", href: "/users/1/computers/5" },
],
user: {
id: 1,
name: "Bob",
computer: 5,
}
}
PUT /users/1
{
name: "Bob",
computer: 4,
}
GET /users/1
{
links: [
{ rel: "computer", href: "/users/1/computers/4" },
],
user: {
id: 1,
name: "Bob",
computer: 4,
}
}
The link URLs can obviously be /computers/n if that's your preference.
This allows your representations to consistently be just data, AND the body of GETs to supply the URLs that your application can use. This way, if you change your URL hierarchy (i.e from /computers/n to /users/m/computers/n) you do not need to change any client code that manually constructs URLs.
By GET you have to use the link to meet with the HATEOAS constraint.
{
id: 1,
name: "Bob",
computer: {uri: "<url>/computers/5"}
}
By PUT you can use the id
{
name: "Bob",
computer: {id: 4}
}
The idea about this that the URIs (or URI templates) must be generated by the server. So the client does not have to know how to build an URI, which makes the service+client code DRY, or in other terms it loosens the coupling between the client and the service implementation.
(You can use a standard (or a draft) solution instead of your custom one to describe hyperlinks. For example: ATOM, XLink, RDF+Hydra, HAL, etc..)
If you're really embracing HATEOAS, you should just use the URI. The URI is your identifier, not the id field. I would remove that entirely. Sure, inside your application you'll have to parse the URI in the payload -- and you already have the parser, obviously -- but It's better for you to do that than asking the client to do.
If you or your clients are sending id fields other than URIs in the payload, or if you're asking the client to parse URIs and figure out semantics, you're defeating the purpose of using HATEOAS, as the client implementation will be coupled to that semantics. The best thing is to embrace URIs as the only identifiers you'll use to drive the interaction with clients.

How to deal with a REST API structures redundancy?

I am currently build a REST API for a webservice that, amongst other things, handles user bans.
The current API I designed look like:
URL: GET /user/<user_id>/bans/<session_id>
Description: Get the ban on the specified session for the specified user.
Output:
{
session_id: 1,
banned_until: "..."
}
URL: GET /user/<user_id>/bans
Description: Get all bans for the specified user.
Output:
[
{
session_id: 1,
banned_until: "..."
},
{
session_id: 2,
banned_until: "..."
}
]
URL: PUT /user/<user_id>/bans/<session_id>
Description: Set or update a ban on the specified session for the specified user.
Input:
{
session_id: 1,
banned_until: "..."
}
Output:
{
session_id: 1,
banned_until: "..."
}
Now one of my coworkers believes that the API is wrong because, for instance in the case of the PUT, the user has to specify the session_id twice: once in the URL and once in the content and those two have to match (which means an extra check server-side). He makes the same comment for the GET where the user specifies the session id in the URL to get it back in the response, meaning a waste of bandwidth.
While I understand his concerns, I however think the current design as it is, is simpler for the user (only one data structure to care about) and that the extra check on the server isn't that much work to do compared to the comfort it brings the user.
Is there an official guideline regarding this in the REST best-practices ? What is the usual/recommended way of dealing with this ?
Personally, I think what you are talking about is the different between the PUT and POST methods.
From the RESTful CookBook:
Use PUT when you can update a resource completely through a specific resource. For instance, if you know that an article resides at http://example.org/article/1234, you can PUT a new resource representation of this article directly through a PUT on this URL.
So, in the PUT example you gave, I think it is perfectly valid to specify the sessionID in the URL since you are storing the ban at a specific point.
However you could also create a POST service at URL: POST /user/<user_id>/bans to satisfy your co-worker. :-)

API design : Need help for URLs

I'm designing a new website. Before i start to code, i'm learning a lot about api and nosql database (as i'm used to sql but i want to try with mongoDB).
In mongoDB, i'll have a 'user' document like that :
{
firstname: 'xxxxxxx',
lastname: 'xxxxxxx',
projects: [
{
name: 'project xxxxxxx',
participants: [], // array of friends into this project
operations: [
{ title: 'Title OP xxxxxxx', contributors: [] },
{ title: 'Title OP xxxxxxx', contributors: [] },
{ title: 'Title OP xxxxxxx', contributors: [] }
]
}
]
}
I was wondering two things :
Should projects.participantsand projects.operations.contributors be references to other users ?
For the API, should i do something like :
GET /users/:id_user
GET /users/:id_user/projects/:id_project
GET /users/:id_user/projects/:id_project/operations/:id_operation
(should my API always start with users ?)
If you ever have a better solution I will be glad to know.
Thanks
EDIT 1 : I'll work on NodeJS with Express and i would like to have a REST API.
yes, projects.participants and projects.operations.contributors can be reference to other documents in the same collection. Each of these should refer to valid _id in the same collection.
can you please put some more light on how exactly are you creating your APIs? I mean which framework you are using as a wrapper to access mongoDB? May be then I can try to help more.
ok great!!!
So, users is your collection name. Its absolutely not necessary to start your API name with users. In node.js you can create a router, which will route your request to a particular js file and you can name it anything you want. Example:
use case: You want to expose 3 API
1. To access all the users. (exposed using url - /getallusers)
2. To access all the participants of the project.(exposed using url - /getparticipantsbyproject)
3. To access all the contributors in the operations.(exposed using url - /getcontributorsbyproject).
You can write all these APIs in your file called myapi and expose them.
Now, you can very well call these APIs from browser using below urls:
http://host:port/myapi/getallusers
http://host:port/myapi/getparticipantsbyproject
http://host:port/myapi/getcontributorsbyproject
Its about RESTful API only. I mentioned 3 urls above which are nothing but RESTful API exposing different functionalities.

How to handle updates to a REST resource when using hypermedia links

I'm working a REST-ful API in which resources which are fairly interrelated. Resources reference each other, and these references may be created or deleted. I'm a little uncertain how to support associating resources together when they reference each other using hyperlinks.
A simple example follows with two resources, A and B.
Resource A:
name: integer
list_b: [list of resource B]
Resource B:
id: integer
description: String
Now, A does not include B in its document, but rather links to it. When using hypermedia, it might look something like this:
Resource A:
{
id: 1,
list_b: [
{ id: 1, href: "https://server/api/b/1" },
{ id: 2, href: "https://server/api/b/2" }
]
}
If a user wants to add or delete one of the B references in A's list, how do they do so, taking into account the presence of the hyperlink? I want the user to be able to update the entire A resource in one PUT operation, but nothing in the output indicates which value for B is required. It make sense to me for the user to perform PUT with content like this:
Resource A:
{
id: 1,
list_b: [
{ id: 1, href: "https://server/api/b/1" },
{ id: 2, href: "https://server/api/b/2" },
{ id: 3 },
]
}
and receive the updated resource (in the response) like this:
Resource A:
{
id: 1,
list_b: [
{ id: 1, href: "https://server/api/b/1" },
{ id: 2, href: "https://server/api/b/2" },
{ id: 3, href: "https://server/api/b/3" }
]
}
My concern is that the user won't necessarily know what to include in the resource when updating resource A's list_b.
When dealing with hyperlinks from one resource to another, how should creates and updates work? Should clients be allowed to update part of the link (the id), or should they be required to update both parts of the link?
Note: I know another approach might be exposing a sub-url for resource A. It could expose list_b as a resource which is operable via HTTP (allowing clients to use POST, PUT, and DELETE on the list resource itself). But this seems less reasonable when A contains multiple references to other resource types. Each field which references another would potentially require a sub-url, which, if there are 10+ fields, is unwieldy, and requires multiple HTTP requests to update the resource.
HATEOAS connects resources together in a RESTful interface, and it's not clear here whether or not the subsidiary objects you're describing really make sense as independent resources. The "AS" part of HATEOAS reminds us of the role that Web pages play as "resources" in a Web application. Each Web page is really an interactive representation of application state (the "application" in this case being a classical, multiple-page Web application), and the hyperlinks to other resources provide the user with transitions to other application states.
A RESTful Web API, having JavaScript code rather than human beings as its client, is naturally data-access-oriented, so few if any of its resources take the form of "application state," per se. In a tradition Web application, you can draw a state transition diagram and clearly see the connections among states, and thus among resources. In a RESTful API, the boundaries among passive data resources are motivated more by the efficiencies of client/server interactions and other subtle forces.
So do your subsidiary objects ("B") here really need to be represent as first-class resources? Are there instances where the front end will enumerate or otherwise access them independent of the aggregates in which they participate ("A")?
If the answer is "no," then they obviously shouldn't be represented hyptertextually in the "A" structure. I presume that the answer is "yes," however, and that you also have good reason to offer all of the other subsidiary objects to which you refer as independent resources. In this case, there's some amount of interface work in the form of routes and controllers that is necessary to support all of those resources no matter what, because your application is presumably providing a means to manipulate them each on their own, or at least query them (through hyperlinks such as those in your example).
This being the case, a POST to the path representing your collection of "B" objects (e.g., "server/api/b") can return a URL in the response's "location" header value as POSTs that create new resources are supposed to do. When your user interactively adds a new "B" to a list belonging to an "A" on your Web page, your front end can first POST the new "B," getting its URL back through the location header on success. It can then incorporate that link into the list representation inside its "A" object before PUTting the updated "A."
The ID value is a bit of a wrinkle, as you'll be tempted to break the encapsulation of the back end by extracting the ID value from the text of the URL. True HATEOAS zealots make their RESTful APIs produce obfuscated, hashed or otherwise unintelligible URLs specifically to frustrate such encapsulation-breaking on the part of clients. Better that the POST of the new "B" object returns a complete representation of the new "B" object, including its ID, in its response body, so that the client can reconstitute the full object and extract the ID from it, thus narrowing the coupling to the resource itself and not the details of the RESTful interface through which it is obtained.
You should also look at the LINK method:
LINK /ResourceA/1 HTTP/1.1
Link: <http://example.com/ResourceB/3>; rel="list_b"
...
204 Yeah Fine, Whatever
This tells /ResourceA/1 to link to /ResourceB/3 using the relationship "list_b".