4 ms·
“Proper” use of a REST or hypermedia API generally requires you only ever initiate communications with the API from the root (https://my.api.example/ https://my
by jsankey 14y ago
“Proper” use of a REST or hypermedia API generally requires you only ever initiate communications with the API from the root (https://my.api.example/ https://my.api.example/ versus https://my.api.example/some/other/url https://my.api.example/some/other/url). From there, every response from the API will then contains links to other resources, often with a relation to explain how each resource relates to the next. In this way, you never guess a URL - you are always given it.
Speaking from practical experience using an API like this: it can result in a lot of extra round trips to get to your final destination. The indirection is nice purity-wise, but in practice do you really want to make 3-4 times the round trips to the server for every API interaction? Especially when you might be on a mobile network? All for the sake of flexibility you may never need?
I'd say supporting the discoverability for learning, and consistency etc is nice. But in practice concerns like this (and the DHH example, and others already in comments here) will crop up and clients will start building their own direct URLs. So the idea that you'll be able to change the URL structure without affecting clients is a pipe dream.
- steveklabnik 14y ago> it can result in a lot of extra round trips to get to your final destination. You can usually get around this. Many people make their resources have too much hierarchy; there's nothing inherently unRESTful about having a flat one. You should _not_ be having 3-4 round trips for every API interaction. Each request is an interaction. Hypermedia APIs expose a workflow, not a data model.
- Milagre 14y ago> Hypermedia APIs expose a workflow, not a data model. I would say this is true of REST APIs. Not necessarily hypermedia APIs. An API that directly exposed a graph database as an HTTP-based API using hypertext/links within resources would still need to be classified as a hypermedia API, but would fail to adhere to the HATEOAS principle. Edit: More specifically - a graph database that exposed itself with links for every edge and a resource for every node.
- steveklabnik 14y agoI personally draw a distinction between "Hypermedia APIs" and 'hypermedia APIs.' The former is 'orthodox REST' and the latter is 'an API that serves up hypermedia.'
- jsankey 14y agoFirst, are there then multiple roots? If so, you've already sacrificed one level of indirection, moving knowledge to the clients. If not, you're adding at least one request. Secondly, when your data is hierarchical, it's nice for other reasons to reflect this in your URI structure. It's intuitive (and thus discoverable in its own way) and can make for human-friendly URLs (especially when your datatypes have natural identifiers).
- steveklabnik 14y ago> You're adding at least one request. It's pretty trivial to have the client hit the root on startup, and then cache that and never make another call. API roots don't change very much. > First, are there then multiple roots? Nope. Here's an example of what I call the 'hypermedia proxy pattern' in Sinatra: https://gist.github.com/3172911 https://gist.github.com/3172911 I based this off of this talk by Jon Moore: https://vimeo.com/20781278 https://vimeo.com/20781278 and demo'd it at the end of this presentation: http://oredev.org/2012/sessions/designing-hypermedia-apis http://oredev.org/2012/sessions/designing-hypermedia-apis Basically, you can fold elements of the collection up into the parent, and the client will automatically make less requests. Jon's presentation goes from 14 requests for the first iteration to 2 on the first hit, 1 every hit thereafter, with no changes to the client. > when your data is hierarchical, it's nice for other reasons to reflect this in your URI structure. Sure! So provide both: one 'deep link' or full collection in the root (or wherever) response, but also serve the data as a separate resource that's hierarchical. Best of both worlds.
- jsankey 14y ago> It's pretty trivial to have the client hit the root on startup, and then cache that and never make another call. API roots don't change very much. That's true and will work in most cases, but perhaps not when client sessions are short-lived. > Basically, you can fold elements of the collection up into the parent, and the client will automatically make less requests. Now it looks like my choices are to either fetch more data than I need, or make more requests than I need. > Best of both worlds. Well, both best and worst of both worlds. Each approach needs to stand up to cost-benefit analysis alone or I doubt it's worth maintaining both. I do see advantages in these patterns, but I think some of them are more theoretical than practical, and I'll take the practical advantage I see today over the theoretical one I might need in the future.