Live data from Hacker News

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

news.ycombinator.com

1–10 of 72 posts

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

#1
If you're building a REST/HTTP API, how do you think about when to express the hierarchy of resources in the URLs?

For example, let's say you had a blog site. Organizations have blogs. Blogs are made up of sections and comment threads. Comment threads have individual comments.

Would you opt for:

- /organizations/:organizationId/blogs/:blogId OR /blogs/:blogId (and get the organization from somewhere else like an auth token)

- /organizations/:organizationId/blogs/:blogId/sections/:sectionId OR /blogs/:blogId/sections/:sectionId OR /sections/:sectionId

- /organizations/:organizationId/blogs/:blogId/threads/:threadId/comments/:commentId... you get the idea

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

#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 others using links (hrefs, or other mechanism for orther media types).

URIs can be anything like /ajndkandkjnasd, totally unreadable for humans. If it is a resource that contains links that can be followed, then it is a system that answers to a uniform interface, and that is the part of the REST dissertation that really matters (the other stuff are just implications of having such uniform interface).

For machine APIs, payloads could use "comment_id", "thread_id" and so on referring to a single resource. If any API users need to build URLs, they would do so by using a single property of the data (which is good enough as a link for me nowadays, for private APIs at least).

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

#5
post #4

In case the organisation is basically a tenant in multi-tenant application I would leave it out of the API and resolve it in another way, but if it is not I would leave it in. Does that make sense?

It is indeed. Could you explain why you’d recommend leaving it out in that case & what you’d recommend instead?

Thanks!

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

#6

In theory, HATEOS is designed to resolve this problem. Quick 3 min draft example: https://gist.github.com/djames-bloom/2131d021a8f6d3d09c5a808...

Thanks for writing that up!

I think it doesn’t quite answer what I’m after though.

I’m thinking less about resource discoverability and more about authorization and fetching resources from the database. For example, if the URL doesn’t include the post ID and I need that to check if the user is authorized to post a comment, I’d first need to look up the comment thread to get the post.

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

#7
post #4

In case the organisation is basically a tenant in multi-tenant application I would leave it out of the API and resolve it in another way, but if it is not I would leave it in. Does that make sense?

It is indeed. Could you explain why you’d recommend leaving it out in that case & what you’d recommend instead? Thanks!

In a multi tenant application you will strictly rely on the authenticated and authorized principal and the company id in which it resides when making every request. So baking it into the route is not great because you're never going to trust the value in the route anyway, you have to refer to the claim in your request.

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

#8
post #7

Earlier quoted context omitted.

It is indeed. Could you explain why you’d recommend leaving it out in that case & what you’d recommend instead? Thanks!

In a multi tenant application you will strictly rely on the authenticated and authorized principal and the company id in which it resides when making every request. So baking it into the route is not great because you're never going to trust the value in the route anyway, you have to refer to the claim in your request.

Good point -- thanks!

I guess the one case where it might still make sense to have the organization ID in the path is if users can be in multiple organizations and some APIs involve listing all of a given resource for a certain organization.

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

#9
I find that having both /foo/:fooId and /bar/:barId/foo/:fooId to basically result in duplicate code/tests or unnecessary complexity. I'll allow /bar/:barId/foo/:fooId in an SPA router though (not http API). In probably most frameworks, each additional route probably encures a microscopic RAM/CPU cost.

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

#10

In theory, HATEOS is designed to resolve this problem. Quick 3 min draft example: https://gist.github.com/djames-bloom/2131d021a8f6d3d09c5a808...

Thanks for writing that up! I think it doesn’t quite answer what I’m after though. I’m thinking less about resource discoverability and more about authorization and fetching resources from the database. For example, if the URL doesn’t include the post ID and I need that to check if the user is authorized to post a comment, I’d first need to look up the comment thread to get the post.

Interesting. I have used HATEOAS for a REST API. All requests were signed with a shared (between client and server) secret key. The shared secret keys were all associated with permissions to resource actions.

In this case, the URLs never included anything in the route path that would have let you know that a user could execute an action. Instead, resource actions were limited to/owned by the shared key. A request to a route that had a different secret key owner would simply fail authorization unless the signature matched. The authorization headers included the API_ID that let the server side know which secret key to use to check the signature.

This felt pretty good to me at the time - I basically looked at what AWS was doing with REST signatures and implemented a version of that for my purposes.

Post reply on HN