Live data from Hacker News

Ask HN: Nested Resources in REST/HTTP API URLs?

news.ycombinator.com

31–40 of 72 posts

Re: Ask HN: Nested Resources in REST/HTTP API URLs?

#31
While things often have parents and children, they also very frequently stand alone. Also, sometimes you don't want to leak private data (org id's) in public content (a blog post)

What I recommend is follow the resource standards from something like jsonapi, and organize your routes like this:

/organizations/:organization_id

/organizations/:organization_id/blogs -> returns a list of links to blogs (maybe including the very most basic data, like blog title and byline)

/blogs/:blog_id -> one blog, has a link to organization, for going "up" the hirearchy, but only returned for authenticated users (if that's necessary in your use case)

/blogs/:blog_id/sections -> links to list of sections

/blogs/:blog_id/threads -> links to list of threads

/threads/:thred_id -> one thread, but links to parents as above

/sections/:section_id -> same as threads

you get the idea.

I've done it this way and I feel like it ends up being very easy to wrap my head around where things are, and how they relate to one another.

One of my favorite example APIs is stripe. the layout makes sense, routes make sense, and it's a very complex system which becomes easy to understand and the routes aren't insanity, if you are looking for a very public example

Re: Ask HN: Nested Resources in REST/HTTP API URLs?

#32
A problem with nested URLs like /organizations/:organizationId/blogs/:blogId/sections/:sectionId is that when you are manipulating a section from the frontend, you don't only need to keep and pass around their sectionId, but also their organisationId and blogId everywhere. Often you'll already have those, but sometimes not and it'll be annoying, you'll have to make more complex code with functions taking more parameters than necessary. From the backend, you'll need to check that all those ids are consistent and match.

It's also possible you will need at some point to re-use sub objects in a new context, so you'll have different kinds of paths to query those sub objects.

I'd go with Python's guideline "Flat is better than nested" here, and in doubt, follow it.

I think nested is only appropriate if you want to ensure the requester knows the oragnisationId, the blogId and the threadId of a particular comment to access it. Otherwise, it will lead to more complexity everywhere.

Re: Ask HN: Nested Resources in REST/HTTP API URLs?

#33
post #3

Just do: - /organizations/:id - /blogs/:id - /sections/:id - /threads/:id - /comments/:id Why? What determines how resources are related are links, not patterns in the URL. It's a graph, the URLs are just nodes, the links are what connect them. If you _want_ to have some sort of hierarchy in the URL, you can redirect: - /organizations/123/blogs/1234 -> /blogs/1234 Then each resource expresses how it is related to oth…

I'd also add that using a flat resource hierarchy also makes it slightly simpler to peel off a resource set, such as /organizations/:id, into a dedicated microservice.

Re: Ask HN: Nested Resources in REST/HTTP API URLs?

#36
post #3

Just do: - /organizations/:id - /blogs/:id - /sections/:id - /threads/:id - /comments/:id Why? What determines how resources are related are links, not patterns in the URL. It's a graph, the URLs are just nodes, the links are what connect them. If you _want_ to have some sort of hierarchy in the URL, you can redirect: - /organizations/123/blogs/1234 -> /blogs/1234 Then each resource expresses how it is related to oth…

The data model matters doesn't it? If it's /org/orgId/blog/blogId and a user has access to only a single orgId and needs to be logged in then doing it in /blog/blogId makes sense. But if a user has acess to multiple orgs via different orgIds, then it makes more sense to do the former with /org/orgId/blog/blogId because then the page is sharable via URL. If you do just /blog/blogId that prevents a user from easily acc…

Just gives blogs unique IDs regardless of the organization. No two blogs ever have the same ID. Now the route doesn't need to provide the Organization ID, because that association lives in the data store for your application and you can infer it.

Re: Ask HN: Nested Resources in REST/HTTP API URLs?

#37
If it’s strictly a tree of relationships (always 1:many) then there are some benefits to having nested IDs. You can do things like attach permissions to the root of the tree, and logging is often clearer (the owner is right there in the URL).

However as soon as you need a M:M or many:1 relationship this breaks down. If a blog can be shared between multiple orgs, how do you represent that?

Therefore as others have recommended, a single ID per URL with a sub-endpoint for the nested list like /organizations/:organizationId/blogs/ (but no two-ID endpoints) is the generalizable and future-proof option. I strongly prefer to keep all the state in the URL rather than hitting /blogs/ and getting the org implicitly from the auth state. Way harder to debug if the auth context can change what results your API produces.

Re: Ask HN: Nested Resources in REST/HTTP API URLs?

#38
post #3

Just do: - /organizations/:id - /blogs/:id - /sections/:id - /threads/:id - /comments/:id Why? What determines how resources are related are links, not patterns in the URL. It's a graph, the URLs are just nodes, the links are what connect them. If you _want_ to have some sort of hierarchy in the URL, you can redirect: - /organizations/123/blogs/1234 -> /blogs/1234 Then each resource expresses how it is related to oth…

This is good for fetching a single item. What if you want to list resources?

Eg. List all comments of a blog?

It has to be GET /blog/:blogid/comments

Then, how about creating a new comment?

It'll be POST /blog/:blogid/comments

When both of these have the blog's hierarchy in the URL, should we take it away when fetching a single item? Or the stay consistent, we should simply do:

/blog/:blogid/comments/:commentid

It's hard.

Re: Ask HN: Nested Resources in REST/HTTP API URLs?

#39
post #3

Just do: - /organizations/:id - /blogs/:id - /sections/:id - /threads/:id - /comments/:id Why? What determines how resources are related are links, not patterns in the URL. It's a graph, the URLs are just nodes, the links are what connect them. If you _want_ to have some sort of hierarchy in the URL, you can redirect: - /organizations/123/blogs/1234 -> /blogs/1234 Then each resource expresses how it is related to oth…

This seems like the most traditional and respectful of REST way to go.

You could try a HATEOAS approach if you want to get a bit more fancy.

https://restfulapi.net/hateoas/

If you are following REST strictly there should be only objects, actions and verbs.

Re: Ask HN: Nested Resources in REST/HTTP API URLs?

#40
post #3

Just do: - /organizations/:id - /blogs/:id - /sections/:id - /threads/:id - /comments/:id Why? What determines how resources are related are links, not patterns in the URL. It's a graph, the URLs are just nodes, the links are what connect them. If you _want_ to have some sort of hierarchy in the URL, you can redirect: - /organizations/123/blogs/1234 -> /blogs/1234 Then each resource expresses how it is related to oth…

This is good for fetching a single item. What if you want to list resources? Eg. List all comments of a blog? It has to be GET /blog/:blogid/comments Then, how about creating a new comment? It'll be POST /blog/:blogid/comments When both of these have the blog's hierarchy in the URL, should we take it away when fetching a single item? Or the stay consistent, we should simply do: /blog/:blogid/comments/:commentid It's…

> This is good for fetching a single item. What if you want to list resources?

You're just asking for one of the most basic features in resource-oriented architectures: query a collection resource with a filter predicate and possibly pagination.

GET /comments?blog=

> Then, how about creating a new comment?

Same thing: just POST it to /comments with a relevant request document, such as

{"blog":,"comment":}

Your POST request then receives a response with a link to the newly-created comment resource, and that's it.

> When both of these have the blog's hierarchy in the URL, should we take it away when fetching a single item?

Resources do not have a hierarchy per se. You've just been passing request parameters through the path. That's it.

> It's hard.

Not really. It's a matter of understanding that resource-based architectures just deal with resources, and not resource hierarchies which don't really exist per se.

What you mean by hierarchy is actually just passing parameters through the path, but those parameters can be passed elsewhere.

Post reply on HN