How to define URI for types of a certain resource - rest

Currently, I have an API for showing a list of spots using this route: GET /spots
I also have an API which gets the details for a certain spot: GET /spots/{spot-id}
Now, I will be making another API, which shows all the categories of the spots. Do you guys know of a proper way to go about with this?
So far I have decided on using GET /spots/categories but my manager said it was kind of weird for the spots resource to have categories.
His current suggestions are GET /spot-categories and GET /spotcategories.
Also, for reference, I have database tables spot and spot_category.
Thank you!

I tend to agree with your manager, your spotcategories look like a different entity altogether, so as a resource it deserves a separate url. That being said, if the goal is to find the categories for a particular spot (as opposed to simply browsing through the different available spotcategories), you should only be able to navigate to them through the spots (presuming your API is on level 3 of the Richardson Maturity Model). As in a link from the spots to the categories (or simply embed them, depending on the usage requirements).
So you might end up with something like
GET /spots/{spot-id}/categories

Related

Rest API design: Managing access to sub-entities

Note: I realize that this is close to being off-topic for being opinion-based, but I am hoping that there is some accepted best practice to handle this that I just don't know about.
My problem is the following: I need to design a Rest API for a program where users can create their own projects, and each project contains files that can only be seen by users that have access. I am stuck with how to design the "List all files of a project" query.
Standard Rest API practice would suggest two endpoints, like:
`GET /projects` # List all projects
`POST /projects` # Create new project
`GET /projects/id` # Get specific project
etc.
and the same for the files of a project.
However, there should never be a reason to list all files - only the files of a single project. To make it more complicated, access management needs to be a thing, users should never see files that are in projects they don't have access to.
I can see multiple ways to handle that:
So the obvious way is to implement the GET function, optionally with a filter. However, this isn't optimal, since if the user doesn't set a filter, it would have to crawl through all projects, check for each project whether the user has access, and then list all files the user has access to:
GET /files?project=test1
I could also make the files command a subcommand of the projects command - e.g.
GET /projects/#id/files
However, I have the feeling this isn't too restful, since it doesn't expose entities directly?
Is there any concencus on which should usually be implemented? Is it okay to "force" users to set a parameter in the first one? Or is there a third alternative that solves what I am looking for? Happy about any literature recommendations on how to design this as well.
Standard Rest API practice would suggest two endpoints
No, it wouldn't. REST practice would suggest figuring out the resources in your resource model.
Think "documents": I should be able to retrieve (GET) a document that describes all of the files in the project. Great! This document should only be accessible when the request authorization matches some access control list. Also good.
Maybe there should also be a document for each user, so they can see a list of all of the projects they have access to, where that document includes links to the "all of the files in the project" documents. And of course that document should also be subject to access control.
Note that "documents" here might be text, or media files, or scripts, or CSS, or pretty much any kind of information that you can transmit over the network. We can gloss the details, because "uniform interface" means that we manage them all the same way.
In other words, we're just designing a "web site" filled with interlinked documents, with access control.
Each document is going to need a unique identifier. That identifier can be anything we want: /5393d5b0-0517-4c13-a821-c6578cb97668 is fine. Because it can be anything we want, we have extra degrees of freedom.
For example, we might design our identifiers such that the document whose identifiers begin with /users/12345 are only accessible by requests with authorization headers that match user 12345, and that all documents whose identifiers begin with /projects/12345 are only accessible by requests with authorization headers that match any of the users that have access to that specific project, and so on.
In other words, it is completely acceptable to choose resource identifier spellings that make your implementation easier.
(Note: in an ideal world, you would have "cool" identifiers that are implementation agnostic, so that they still work even if you change the underlying implementation details of your server.)
I have the feeling this isn't too restful, since it doesn't expose entities directly?
It's fine. Resource models and entity models are different things; we shouldn't expect them to always match one to one.
After looking further, I came across this document from Microsoft. Some quotes:
Also consider the relationships between different types of resources and how you might expose these associations. For example, the /customers/5/orders might represent all of the orders for customer 5. You could also go in the other direction, and represent the association from an order back to a customer with a URI such as /orders/99/customer. However, extending this model too far can become cumbersome to implement. A better solution is to provide navigable links to associated resources in the body of the HTTP response message. This mechanism is described in more detail in the section Use HATEOAS to enable navigation to related resources.
In more complex systems, it can be tempting to provide URIs that enable a client to navigate through several levels of relationships, such as /customers/1/orders/99/products. However, this level of complexity can be difficult to maintain and is inflexible if the relationships between resources change in the future. Instead, try to keep URIs relatively simple. Once an application has a reference to a resource, it should be possible to use this reference to find items related to that resource. The preceding query can be replaced with the URI /customers/1/orders to find all the orders for customer 1, and then /orders/99/products to find the products in this order.
This makes me think that using solution 2 is probably the best case for me, since each file will be associated with only a single project, and should be deleted when a project is deleted. Files cannot exist on their own, outside of projects.

Proper usage of OpenAPI 3.0.2

I started using OpenAPI a few months ago, but I'm finding multiple caveats while generating documentation. This of course leads me to believe that I must be doing something wrong.
So, I usually begin always by creating the schemes for the multiple resources of my API, I then place a reference to the schemes on the request bodies for each respective endpoint. However I find that this approach makes generated documentation confusing, adding for example an id parameter on the request body of a user create operation when it's clearly not supposed to be there (Of course the user is being created at this point, so there isn't even an ID in the first place, and why would an ID be part of the request body?).
I ended up just making multiple schemes for a single data model, I would choose which one I used based on the operation (E.g. Creating vs Displaying), this way I could generate documentation more accurately. This helps me avoid situations like displaying relations that are generated post-creation on a create operation. (I know I'm probably not phrasing all this correctly but just bear with me).
In a nutshell, I'll end up with approximately 3 or 4 schemes per data model. For the User model I'll have for example User, UserNew, UserSubscriptions, UserAll. All schemes represent the same resource, they just differ in the data that they display.
Again, I feel like this is not the way that OpenAPI is meant to be used. So I hoped that maybe someone here that has more experience with this could guide me on the right path! Thank you.

Restful resource naming for "secondary" tables

Let's go with my example, I have 3 tables and I want to know what's the best method to name my resource url.
Tables:
building
building_type The most simple to define is #1.
API resources:
GET someapi.com/buildings
GET someapi.com/**?**
My problem is that I don't know what's the best practice for "secondary tables" like building_type.
Maybe:
GET someapi.com/buildings/types
GET someapi.com/building-types
...
I hope some of you will reach to enlighten me. Thanks.
You first need to figure our the requirements for your API, the scenarios, use cases etc, and only then actually start building it.
To go back to your question, I'd go for GET someapi.com/buildingTypes, because /buildings/types will leave you with a "Types" resource which doesn't make much sense on it's own. You could indeed make it so it's only accessible once you go to the buildings resource, so GET someapi.com/buildings/buildingTypes could be the way to navigate to it.

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.

implementing the REST way

I did not realise the power of REST until I started using scaffolds in rails. This makes life so simple. Now everytime I try to develop a web application I only think of those 6 verbs. But I have a doubt. How is search related to REST.
Basically the search page which contain a form for the user to input a search term.
which verb does this come under? Is it list??
and what does the search results come under? show?
Search is GET on the collection with some fancy attributes:
GET /articles?q=RESFful+Architecture&in_title=1
Something like that.
There are plenty of resources on the subject, check out Handling arbitrary actions, on ajaxpatterns, for example.
If I understand what you are saying properly, the search page wouldn't be a part of the rest service, but would submit to it.
The search results would be a list of whatever the first class object you had defined was. The Uri would describe the resource that was being displayed.
Retrieving resources is always done with a GET
eg: GET /cars?term=hyundai+green