REST, getting additional information for an SPA - rest

I'm trying to understand this from a REST theoretical perspective.
You have a book collection, it's an entity you can get, delete, etc.
You have an individual book, you get it with an id, delete it with an id, etc
You have an Angular app where you can add new books. So you get the book collection, add a book locally, haven't sent it to the server yet
You need additional info on the book before you add it, for example you need to know if there are any other books with the same title
Can you have multiple GET calls in a RESTful architecture for the same entity? i.e. one with id and another with a name? So you could try to GET the book with the name to see if it already exists
Where does 'get additional info for an as of yet uncreated entity' fit into this? Lets say you need an image for the book and you have stock images, I'm assuming that the images are entities in and of themselves so they have their own REST APIs

If I understand your question correctly, you basically want to do a search on some criteria (name, etc) to check that the book does not already exist. You can use GET for book which would not include id as a path variable but would include the criteria filter params as request parameters(query string). Something like this:
/book?name=bookname -- List book with name as bookname
/book/{id} -- List book with given id
Multiple GET calls for the same entity is not encouraged in a RESTful architecture.

Can you have multiple GET calls in a RESTful architecture for the same entity?
Jim Webber: You should expect to have many many more resources in your integration domain than you do business objects in your business domain.
So sure, why not? How could the client possibly know?
Where does 'get additional info for an as of yet uncreated entity' fit into this?
When in doubt, try to envision what you are doing as a web page. Would be be reasonable to send to ask the web server for a form to add a new book with a particular title, and have it return the form, a list of known books with similar titles, a set of stock images, etc? Of course. So it's going to be fine for your API to do the same thing.
Or perhaps the form should be a separate idea, and the search results should look like a link to the form, and a bunch of links to representations of existing books. That's also fine.
Using links from unstable things to stable things is often a good idea, because it affords caching.

Related

How to name REST API endpoints for very especific features?

So, I'm building a RESTful API, that's like a Parking system, it have ParkingLots and Cars that enter or leave ParkingLots, at this moment, my endpoints looks like this.
POST '/parking-lots' // To create a ParkingLot
POST '/cars' // To create a Car
But, how to name an endpoint that has EnterParkingLot or LeaveParkingLot feature following REST best pratices? I didn't found an article or blog post that answer this question so far.
But, how to name an endpoint that has EnterParkingLot or LeaveParkingLot feature following REST best pratices? I didn't found an article or blog post that answer this question so far.
The key abstraction of information in REST is a resource. Resources are generalizations of documents, not endpoints.
Useful work is a side effect of editing documents (Webber, 2011).
If you are having trouble figuring out the URI, that probably means that you haven't been thinking enough about the documents (aka you don't yet have a clear understanding of your "resource model").
One idea that can sometimes help is to think about a client with cached documents. When they send you one of these messages, which document in the cache is the most important one to invalidate?
In REST, it is normal (not necessarily common) to have a single resource handle many different kinds of edits. For instance, we might submit an EnterParkingLot form, that would update a parking lot resource, and then later submit a LeaveParkingLot form that updates the same parking lot resource (with the code on the server parsing the requests to distinguish the different kinds of edits).
But it would also be fine to add a "parking ticket" resource to your resource model, with a different ticket tracking the arrival and departure of each car.
Domain experts are typically good at telling you what the documents are, and what names make sense.
I would do it like:
POST '/parking-lot/$n/enter'
POST '/parking-lot/$n/leave'

In general, would it be redundant to have two GET routes for users (one for ID and one for username)?

I'm building a CRUD for users in my rest API, and currently my GET route looks like this:
get("/api/users/:id")
But this just occured to me: what if a users tries to search for other users via their username?
So I thought about implementing another route, like so:
get("api/users/username/:id")
But this just looks a bit reduntant to me. Even more so if ever my app should allow searching for actual names as well. Would I then need 3 routes?
So in this wonderful community, are there any experienced web developers that could tell me how they would handle having to search for a user via their username?
Obs: if you need more details, just comment about it and I'll promptly update my question 🙃
how they would handle having to search for a user via their username?
How would you support this on a web site?
You would probably have a form; that form would have an input control that would allow the user to provide a user name. When the user submit the form, the browser would copy the form input controls into an application/x-www-form-urlencoded document (as described by the HTTP standard), then substitute that document as the query_part of the form action, and submit the query.
So the resulting request would perhaps look like
GET /api/users?username=GuiMendel HTTP/x.y
You could, of course, have as many different forms as you like, with different combinations of input controls. Some of those forms might share actions, but not necessarily.
so I could just have my controller for GET "/api/users" redirect to an action based on the inputs?
REST doesn't care about "controllers" -- that's an implementation detail; the whole point is that the client doesn't need to know how the server produces a representation of the resource, we just need to know how to ask for it (via the "uniform interface").
Your routing framework might care a great deal, but again that's just another implementation detail hiding behind the facade.
for example, there were no inputs, it would return all users (index), but with the input you suggested, it would filter out only users whose usernames matched the input? Did I get it right?
Yup, that's fine.
From the point of view of a REST client
/api/users
/api/users?username=GuiMendel
These identify different resources; the two resources don't have to have any meaningful relationship with each other at all. The machines don't care (human beings do care, so we normally design our identifiers in such a way that at least some human beings have an easy time of it -- for example, we might optimize our identifiers to make things easy when operators are reading the access logs).

REST: Get query only changeable objects

I'm having a bunch of apis which return several types of data.
All users can query all data by using a GET rest api.
A few users can also change data. What is a common approach when designing REST API, to query only the data that can be changed by the current user but still allow the api to return all data (for display mode).
To explain it further:
The software manages projects. All projects are accessible for all users (also anonymous) via an api (let's call it GET api/projects).
A user has the ability to see a list of all projects he is involved in and which he can edit.
The api should return exactly the same data but limited to the projects he is involed in.
Should I create an additonal parameter, or maybe pass an http header, or what else?
There's no one-size-fits-all answer to this, so I will give you one recommendation that works for some people.
I don't really like creating resources that have 'complex access control'. Instead, I would prefer to create distinct resources for different access levels.
If you want to return limit results for people that have partial access, it might be better to create new resources that reflect this.
I think this might also help a bit thinking about the abstract role of a person who is not allowed to do everything. The abstraction probably doesn't exist per-property, but it exists somewhere as a business rule.

Hypermedia API: How to document properly?

I am in the middle of developing my first Hypermedia API. I thought I had a good grasp of things but when It comes to documenting the API, I start to question my understanding of the whole concept.
The core of the question comes down to documention, but It might be that I did not understand one or more aspects correctly. If so, please tell me :-)
Documenting Link Relations
Let's say I have a more or less generic link relation (https://example.com/rels/accounts) in my API to link related accounts. The exact meaning can change on context, right?
On my billboard (or index), I might have a link with that relation to browse all accounts.
On another resource, account group for example, it might just link to a specific subset of accounts belonging to that group.
How should I document that relation? Just saying that this is a link to a collection of accounts seems not enough. However, that is exactly what RFC5988 does, just describing what the link itself means. So that might be the way to go.
The problem gets worse with actual state transitions. Let's use https://example.com/rels/create-account as our example here. If the documentation just says "This is where you create a new account", It makes no statements on what I have to do with that link to create a resource. Where would the documentation be that states something along the lines:
You either POST multipart/form-data or application/json to this endpoint that contains at least the following fields [...]
The relation itself does not seem to be the right place. Especially when you consider that the payload to that URL might also change on context. In our example, having that relation on an account group would make it mandatory to omit the accountGroup field because the value is provided by the context.
Documenting Profiles
As far as I understood it, I can (and probably should) have a profile for each resource in my API, documenting the resource itself. This would include its properties and links that can occur. Would that be the place where I specify what the link means exactly?
Sticking to my earlier example, would I document for profile https://example.com/profiles/account-group that the link with the relation https://example.com/rels/accounts links to a collection of accounts that are part of this group?
That makes sense to me, but when we go into actual state transitions things seem to get messy.
State transitions
Let's say the client navigated to an account collection from an account group. The resource itself would not really differ from the resource that contains all global accounts. It would have pagination links and the links to the account resources themselves.
If that account-collection resource has a link with the relation type https://example.com/rel/create-account I would be in deep trouble, right? Because the information that this is an account-collection containing just accounts of a certain group is not encoded in the profile
https://example.com/profiles/account-collection and can therefore not contain the information that clients have to omit the accountGroup property when posting to that resource.
Concrete Questions
Am I right that relations definitions should be weak and not contain any information about how I can interact with the resource it links to?
If so, can I expect from client to follow a link and then discover what they can do, based on the profile of that resource. This seems wrong, especially for state transitions.
If profiles should document what a client might do with the linked resources, I cannot transport context across multiple "jumps" within the API, correct?
Should I use even more profiles and relations? https://example.com/profiles/global-accounts and https://example.com/profiles/account-group-accounts come to mind.
The more I think about it, I must either miss a critical piece or it's something that can be solved in multiple ways. Because of that, I am aware that there might be no 100%-correct answer to this question. But maybe someone can enlighten me so that I can make my own trade-offs? :)
Let's take your points one at a time:
1. Link relation meaning based on context
To reformulate your question into code context: How do I document the "getAccounts()" method when it means something different in the class Billboard and AccountGroup?
The obvious answer is you don't document the method in general, but you document the classes and within them the methods. The RFC you're referring to tries to define relations that are in some sense generic, or should mean the same thing every time. You might re-use some of them, but you still have to document the method and what they mean in your class.
Class equals to your Media Type. So I propose you document your Media Type.
2. Links and Forms, how to define what to POST
If you document your Media-Types, you can define whatever you like in there, including how to use its links. However, I would recommend not defining the Media Type of the POST, but letting it up to Content-Negotiation.
The client knows it has to POST an Account, it will use some Media-Type it thinks is proper for this task. The server will then tell the client whether that format is acceptable or not, it can also give a list of acceptable Media Types in return.
3. Documenting Profiles
If by Profiles you mean Media-Types, then yes, you should document them. You should actually only document Media-Types.
4. State transitions, modifications to representations based on state
Since the account group is a resource anyway, the client should not actually supply it, it should be part of the "state" which group the new account belongs to.
In other words, the client gets a link, that already has the context of the current account group. The client has to post a generic account, but the server knows it should belong to the group in the current state (it is part of the URI for example)
So no, the client shouldn't know it has to omit some parameter.
5. Question
Yes, relations should not define how to interact with the resource. Media Types could actually do that (like Forms defining it must be a POST, etc.), but more often than not it's not necessary.
Yes, clients discover not only what transitions are available (links), but what methods are available. The methods (GET, POST, PUT) always mean the same thing, and they are not described in Media-Types, since Media-Types only describe representations, not resources. The server normally submits all the supported methods in a response, or explicitly in response to OPTIONS.
I still don't really know what you mean by "Profile". If you mean relation profile, as in some data in the link definition, then no. The context/state travels in the URI. You can use the URI to "save" that the client is moving inside one account group for example.
No, you shouldn't add semantics to link relations. The Media-Type adds the semantics to links.
HTH
I will try to answer more succinctly than Robert's answer, which I think can get confusing.
Let's say I have a more or less generic link relation (https://example.com/rels/accounts) in my API to link related accounts. The exact meaning can change on context, right?
No. The meaning of a link relation is static. Your "list of accounts" relation on your index (list of lists) page is specific to your application. In your other example, account group, you are already in a "collection" resource, and members of that collection have link relation "item" (see the list of IANA link relations).
The problem gets worse with actual state transitions. Let's use https://example.com/rels/create-account as our example here. If the documentation just says "This is where you create a new account"
I would instead add a "create-form" link (another standard IANA link relation) to the "list of accounts" page. Your clients would then go: start -> list-of-Xes -> create-form -> submit. There would be no "create-an-X" or "create-a-Y" link relations. You probably would not allow clients to create new collection types either. This makes navigating the API lengthier for clients but reduces the amount of stuff they need to know (API breadth).
Would [a profile] be the place where I specify what the link means exactly?
If you make your link relations generic except for one to describe each model class, you will not have to document these in profiles on a per-model-class basis.
If that account-collection resource has a link with the relation type https://example.com/rel/create-account I would be in deep trouble, right?
Yes, so don't do that! What you are describing there is linking an existing resource to a collection (by IANA's definition). What I would advise is that you support clients being able to do this:
LINK http://site/account-collections/some-collection HTTP/1.1
Link: <http://site/accounts/some-account-id>; rel=item
Authorization: Token abc123
This simple (complete!) HTTP request has the semantics of adding an "item" link containing the existing account's URI to the collection you wish to add it to. It does not create a new account. The LINK method is still in draft but has existed in some form since HTTP 1.1 (1997).
Robert wrote:
You should actually only document Media-Types.
I disagree. You should document link relations too, but try not to create them if you can use an generic one.

Include / embed vs. link in RESTful APIs

So the general pattern for a RESTful API is to return a single object with embedded links you can use to retrieve related objects. But sometimes for convenience you want to pull back a whole chunk of the object graph at once.
For instance, let's say you have a store application with customers, orders, and returns. You want to display the personal information, all orders, and all returns, together, for customer ID 12345. (Presumably there's good reasons for not always returning orders and returns with customer personal information.)
The purely RESTful way to do this is something like:
GET /
returns a list of link templates, including one to query for customers
GET /customers/12345 (based on link template from /)
returns customer personal information
returns links to get this customer's orders and returns
GET /orders?customerId=12345 (from /customers/12345 response)
gets the orders for customer 12345
GET /returns?customerId=12345 (from /customers/12345 response)
gets the returns for customer 12345
But it'd be nice, once you have the customers URI, to be able to pull this all back in one query. Is there a best practice for this sort of convenience query, where you want to transclude some or all of the links instead of making multiple requests? I'm thinking something like:
GET /customers/12345?include=orders,returns
but if there's a way people are doing this out there I'd rather not just make something up.
(FWIW, I'm not building a store, so let's not quibble about whether these are the right objects for the model, or how you're going to drill down to the actual products, or whatever.)
Updated to add: It looks like in HAL speak these are called 'embedded resources', but in the examples shown, there doesn't seem to be any way to choose which resources to embed. I found one blog post suggesting something like what I described above, using embed as the query parameter:
GET /ticket/12?embed=customer.name,assigned_user
Is this a standard or semi-standard practice, or just something one blogger made up?
Being that the semantics of these types of parameters would have to be documented for each link relation that supported them and that this is more-or-less something you'd have to code to, I don't know that there's anything to gain by having a a standard way of expressing this. The URL structure is more likely to be driven by what's easiest or most prudent for the server to return rather than any particular standard or best practice.
That said, if you're looking for inspiration, you could check out what OData is doing with the $expand parameter and model your link relation from that. Keep in mind that you should still clearly define the contract of your relation, otherwise client programmers may see an OData-like convention and assume (wrongly) that your app is fully OData compliant and will behave like one.