REST Route/Input Design - rest

I have one Restaurant to many Menu, one Menu to many Category, one Category to many Item. I'm stuck trying to find the best way to lay out the routes for these models. Here are the options I see:
I can flatten the routes and simply require the id of the parent model.
this makes the routes simple, but requires an extra input/parameter every time I want to do anything with the model.
GET /menus?restaurant_id=X
POST /menus?restaurant_id=X&name=foo&description=bar
I can nest all the routes within their given parent models.
this makes the routes long, but doesn't require any extra inputs/parameters
this adds unnecessary information to certain lower-level models (don't need to know restaurant directly when accessing categories/items)
GET /restaurant/:restaurant_id/menus
POST /restaurant/:restaurant_id/menus?name=foo&description=bar
GET /restaurant/:restaurant_id/menus/:menu_id/categories/:category_id/items
Is there a good standard for which to choose?

I would go with your very last example - I try to keep URL params to a minimum for readability and cache/proxy concerns.

I would design it as such:
menus
POST /menus?restaurant_id=123&name=foo&description=bar
GET /menus?id=890 // specific menu
GET /menus?/restaurant_id=123 // many menus
Items
POST /items?category_id=594&name=milkshake&description=vanilla
more generically
POST /<model_of_interest>?<parent_of_model_of_interest>&<other>&<parameters>
GET /<model_of_interest>?<model_of_interest_id>
As you can see this would work for your top most and bottom most model without any additional cruft. Then validate the request and enforce access with your models which should be easily abstracted given the "only one parent" scheme you are going for (i.e. by passing &category_id=345 to create item route, you can easily construct the rest of your object and know for certain that 345 can only ever belong to menu_id=123 which can only even belong to restaurant_id=...).
This has the benefits of :
not providing information the parent models already have
allowing specific selection of a singular object "downwards" (e.g. give me item where id=338)
allowing universal selection downwards (e.g. give me all items where category_id=123)

Related

PATCHING/ PUTTING generated properties in REST API

I have been struggling to find information on how a resource that contains generated values is modified. Below is a real world example:
Let's say we have 2 endpoints:
/categories and /products.
A category is used to contain various parameters that define any product belonging to it. For example, based on a category a product expiration date might be calculated, or some other properties might or might not be attached to a product.
Let's say we create a new product by sending a POST request to /products and among other fields we include the category ID property. Based on the category set a server creates and stores a new product along with various properties generated (expiration date, delivery policies) etc.
Now the problem arises when needing to modify (PATCH/ PUT) the mentioned product.
How are generated values edited? We can for example change a delivery policy, but then the product will contain a field that doesn't match what its attached category describes. Likewise, it might be very handy to modify its generated expiration date, however yet again that can create confusion about why a category says it should expire in 3 days but the product is set to expire in 20 days.
Another solution would be to make all these properties read-only and only allow regenerating them by changing the category, just like at creation.
However that poses 2 problems:
The biggest one being that a different category might not contain the same policy layout. For example, one category might enable generating GPS coordinates to ease the delivery, the other category does not. If we change the category, what do we do with these valuable properties already present? Do we drop them for the sake of clarity?
Another issue is limited flexibility. There might be cases when a property needs to be changed but the category needs to remain the same.
I think these questions are met and answered in probably every single REST API development and probably I am just missing something very simple and obvious. Could you help me understand the right way of going about this?
Thank you very much.
I think these questions are met and answered in probably every single REST API development and probably I am just missing something very simple and obvious. Could you help me understand the right way of going about this?
You write code to ensure that all of the invariants hold for the server's copy of the resource.
That can mean either (a) inspecting the body of the request, and returning a client error if the body doesn't satisfy the constraints you need to maintain, or (b) changing your resource in a way that doesn't exactly match the request you've received.
In the second case, you need to have a little bit of care with the response metadata, so that you don't imply that the representation of the request has been adopted "as is".
The code you are writing here is part of the origin server's implementation, deliberately hidden by the HTTP facade you present. The general purpose components in the middle don't care about those details; they just want you to use messaging semantics consistent with the HTTP (and related) specifications.

REST API Design - Single General Endpoint or Many Specific endpoints

This is a relatively subjective question, but I want to get other people's opinion nonetheless
I am designing a REST Api that will be accessed by internal systems (a couple of clients apps at most).
In general the API needs to update parameters of different car brands. Each car brand has around 20 properties, some of which are shared between all car brands, and some specific for each brand.
I am wondering what is a better approach to the design for the endpoints of this API.
Whether I should use a single endpoint, that takes in a string - that is a JSON of all the properties of the car brand, along with an ID of the car brand.
Or should I provide a separate endpoint per car brand, that has a body with the exact properties necessary for that car brand.
So in the first approach I have a single endpoint that has a string parameter that I expect to be a JSON with all necessary values
PUT /api/v1/carBrands/
Whereas in the second approach in the second scenario I have an endpoint per type of car brand, and each endpoint has a typed dto object representing all the values it needs.
PUT /api/v1/carBrand/1
PUT /api/v1/carBrand/2
.
.
.
PUT /api/v1/carBrand/n
The first approach seems to save a lot of repetitive code - afterall the only difference is the set of parameters. However, since this accepts an arbitrary string, there is no way for the enduser to know what he should pass - he will need someone to tell it to him and/or read from documentation.
The second approach is a lot more readable, and any one can fill in the data, since they know what it is. But it involves mostly replicating the same code around 20 times.
Its really hard for me to pick an option, since both approaches have their drawbacks. How should I judge whats the better option
I am wondering what is a better approach to the design for the endpoints of this API.
Based on your examples, it looks as though you are asking about resource design, and in particular whether you should use one large resource, or a family of smaller ones.
REST doesn't answer that question... not directly, anyway. What REST does do is identify that caching granularity is at the resource level. If there are two pieces of information, and you want the invalidation of one to also invalidate the other, then those pieces of information should be part of the same resource, which is to say they should be accessed using the same URI.
If that's not what you want, then you should probably be leaning toward using separated resources.
I wouldn't necessarily expect that making edits to Ford should force the invalidation of my local copy of Ferrari, so that suggests that I may want to treat them as two different resources, rather than two sub-resources.
Compare
/api/v1/carBrands#Ford
/api/v1/carBrands#Ferrari
with
/api/v1/carBrands/Ford
/api/v1/carBrands/Ferrari
In the former case, I've got one resource in my cache (/api/v1/carBrands); any changes I make to it invalidate the entire resource. In the latter case, I've got two resources cached; changing one ignores the other.
It's not wrong to use one or the other; both are fine, and have plenty of history. They make different trade offs, one or the other may be a better fit for the problem you are trying to solve today.

REST API URL pattern for path parameters

I am building a Backbone app which displays interactive facsimiles of diagrams from certain technical manuals. Each manual has a number of diagram types (say A-Z), distributed over its pages. Each diagram might occur more than once across the pages, and sometimes a single page might contain more than one instance of a given diagram type.
I have a Django backend serving a REST API which my frontend consumes. What I have been struggling with is the design of the url for the request. I have tried several patterns, none of which satisfy me. My Django model looks something like this:
class Diagram(models.Model):
type = models.CharField(max_length=1)
page = models.IntegerField(default=1)
order = models.IntegerField(default=1)
data = JSONField(default='{}')
The order field relates to a situation where there is more than one instance of the given diagram type on a page. The table for this model is read-only, so I am just doing simple GETs. Users only view one diagram instance at a time. A diagram is selected by type, page, and (where relevant) order. My initial url design was this:
example.org/api/diagrams/A/pages/1/order/2/
Although there is a plurality of diagrams, the diagrams param suggests a collection - but the diagrams don't 'contain' pages. Same with the pages param. Obviously order can only be singular. So perhaps:
example.org/api/diagrams/type=A/page=1/order=2/
Or perhaps just go with query params:
example.org/api/diagrams/?type=A&page=1&order=2
Personally I prefer path parameters, but the main complication of this is that the order param is actually redundant most of the time - there are only a small number of cases of repetition of a diagram on a page (currently I default order to '1', both on the backend and in the request). So perhaps a combination of both path and query parameters:
example.org/api/diagrams/A/page/1/?order=2
Is this a good pattern? Are there other alternatives I could consider?
Edit: After some additional reading (notably the URI Standard) I think the answer is that a path parameter design is suited for a hierarchical structure... which seems intuitive. But I don't have that, so the right candidate is the pure query parameter design. Right?
Could I suggest a different approach? I know, that may not be the answer you are looking for, but instead of trying to publish the exact object model from your code, think about what "kind" of resource the client needs to see and what is it related to.
For example if the client needs to "browse" the diagrams, you could have 2 media-types, one for listing all diagrams, and for a single diagram itself. The URIs could be:
/api/diagrams/ <-- list of all diagrams with titles
/api/diagrams/1 <-- a single diagram
/api/diagrams/2
...
If the client needs to browse per manual per page, then you can offer those too with additional media-types representing a manual (list of pages), and the pages with links to the diagrams that are on it. For example:
/api/manuals <-- list of all manuals
/api/manuals/1 <-- list of pages, maybe a list of all diagrams in manual
/api/manuals/1/page2 <-- list of diagrams on page2
The same for your case about browsing per order and diagram type.
If you only need a "search" API, and not a "browse" API, then the proper solution would be to create a "form" in which you can submit the information (order, type, page, etc.). So that would be 2 media-types, one for the search description, and probably one for diagrams.
The point is, URI should not be fixed if you are trying to create a REST API. The server should provide the URIs to the client (except for the start URI, the search page for example).
This has several advantages, one being that you can control your URIs on the server. You don't have to be RESTful though, if you don't want to, but even then the URI itself does not really matter if you control the client anyway. Neither your approaches is wrong by objective measures.
Sorry if that does not help.:)

What's the correct RESTful way to structure A Website's Parent/Child Views

NOTE: This is not specifically for an API.
I have three Entities: Building Unit Person
These are pure simple easy Exclusive 1:M relationships
A Person can only live in (1) unit
A Unit can only exist in (1) unit
The Building is essentially the parent.
Should I have URLs like:
The View mode is pretty easy
/buildings //Show all buildings
/buildings/[id] //Show one building
/buildings/[id]/units //Show all units in a building
/buildings/[id]/units/[id]/people //Show all people in a unit
However, this seems kind of verbose. While those URLs may work for PUTS and POSTS which redirect to a GET, if I want to show all the units and people in a building, should I be using a route like buildings/[id]/details or is there some other standard convention?
Also, when I want to display a form to edit the values, is there a standard url path like buildings/[id]/edit A POST and a PUT in this case will essentially be using the same form ( but with the PUT having the fields filled out ) .
I think your question may attract some opinionated answers, but it'd be good to hear about other peoples' practices regarding RESTful API designs.
You say your paths seem kind of verbose, and you may feel that way if your IDs are auto incremented integers and the only way to specify buildings, units, etc is with paths like
buildings/1/units/4/tenants
buildings/1/units/4/tenants/5
To me these are clear interfaces. If I had to maintain your code, I'd think it's pretty obvious what's going on here. If I had to criticize something, I would say you seem to be developing in a way that allows for all or one selection. It's your design choice, though. Maybe that's exactly what you need in this case. Here are some examples that come to mind.
update one tenant
PUT buildings/1/units/4/tenants/2
create three units
POST buildings/2/units //carries message body for SQL in back end
read tenants with certain criteria
GET buildings/1/tenants?params= //GET can't carry a message body
delete tenants with certain criteria
DELETE buildings/5/tenants?criteria= //params needed?

Aggregate Pattern and Performance Issues

I have read about the Aggregate Pattern but I'm confused about something here. The pattern states that all the objects belonging to the aggregate should be accessed via the Aggregate Root, and not directly.
And I'm assuming that is the reason why they say you should have a single Repository per Aggregate.
But I think this adds a noticeable overhead to the application. For example, in a typical Web-based application, what if I want to get an object belonging to an aggregate (which is NOT the aggregate root)? I'll have to call Repository.GetAggregateRootObject(), which loads the aggregate root and all its child objects, and then iterate through the child objects to find the one I'm looking for. In other words, I'm loading lots of data and throwing them out except the particular object I'm looking for.
Is there something I'm missing here?
PS: I know some of you may suggest that we can improve performance with Lazy Loading. But that's not what I'm asking here... The aggregate pattern requires that all objects belonging to the aggregate be loaded together, so we can enforce business rules.
I'm not sure where you read about this "Aggregate Pattern". Please post a link.
One thing it could be is where we encapsulate a list into another object. For a simple example if we have a shopping cart instead of passing around a list of purchases we use a cart object instead. Then code that works on the whole cart (eg. getting total spend) can be encapsulated in the cart. I'm not sure if this is really a pattern but google found this link: http://perldesignpatterns.com/?AggregatePattern
I suspect when you say
"The aggregate pattern requires that
all objects belonging to the aggregate
be loaded together, so we can enforce
business rules. "
this depends on your business rules.
Generally patterns should not be regarded as a set of rules you must follow for everything. It is up to you as a developer to recognise where they can be used effectively.
In our cart example we would generally want to work on the whole cart at once. We might have business rules that say our customers can only order a limited about of items - or maybe they get a discount for order multiple items. So it makes sense to read the whole thing.
If you take a different example eg. products. You could still have a products repository but you needn't not load them all at once. You probably only ever want a page of products at a time.