How Do Hypermedia Clients Not Break?

82 views
Skip to first unread message

Fabian Ockenfels

unread,
Sep 12, 2016, 1:56:22 PM9/12/16
to Hypermedia Web
I'm currently investigating the possible benefits of a proper REST API, but am uncertain if I understand the concept correctly.

For example, if I wanted to get the third ordered item associated with a specific payment, in a traditional level 2 API I would
GET myapi.com/payments/123/items/3

However in a REST API I am supposed to not need any out of band information except for the entry point. So I cannot make any assumptions about the URL structure or available resources.
To achieve the same functionality I would need to
Hit root    -- GET myapi.com
Follow link -- GET myapi.com/payments/123
Follow link -- GET myapi.com/payments/123/items/3

Is this correct? Do I always have to start at the root?

As long as I do not enforce opaque URLs, I guess my clients would still be able to access the required information directly and use the response links to navigate from there on. But in this case they would break with API changes, e.g. payments --> mypayments, as their entry point of choice would have moved.

If the traversal of links relative to root is the only option to avoid client breakage, doesn't that affect performance a lot? After all I'm doing three times as many requests for an request as simple as this example. And that is if I included links to individual payments and items on the root and payment endpoints respectively. If I didn't it would probably look more like this
GET myapi.com                    -- {users, payments}
GET myapi
.com/payments           -- {payments/1, payments/2, ..., payments/n}
GET myapi
.com/payments/123       -- {payments/123/items, payments/123/somethingidontneed}
GET myapi
.com/payments/123/items --
{payments/123/items/1, payments/123/items/2, ..., payments/123/items/n}
GET myapi
.com/payments/123/items/3
where {...} denotes the possible transfer options returned by the server.

I could significantly lower the amount of requests by embedding data, but then I would be sending huge amounts of unrequested data.

Are there any best practices how to actually work with hypermedia APIs?

mca

unread,
Sep 12, 2016, 8:32:35 PM9/12/16
to hyperme...@googlegroups.com
some things to consider....

1) Hypermedia is not URLs. Hypermedia is the in-line instructions on what a client/user can *do* at the moment. in HTML and other formats, these instructions appear as links and forms. <a href="...">...</a> is a hypermedia control. so is <img src="..." />. one is for navigating to another location. the other for loading content from another location. 

2) Using Hypermedia controls allows services to using static identifiers for changing URLs. <a href="/pay" class="payments" /> allows a client to memorize the class ("payments") and treat the URL as opaque. That means when the service changes the URLs for "payments" clients don't have to break (e.g. <a href="/secure/pay" class="payments" />).

3) The notion that "a hypermedia client should only need a single URL to start" is only 1/2 the story. Yes, the client/user should be able to start w/ only 1 URL (and this URL ends up being assured over a long period of time). But that is only needed to *start* -- not *forever*. IOW, once I start at the assured URL (<a href="http://myapi.com" class="home"/>) and then navigate to the the location for payments (e.g. <a href="/secure/pay/open-orders" class="payments" />) it is perfectly fine (and smart) for my client app to "memorize" the URL and identifier (store somwhere) for future use so that next time it can directly call the "payments" URL. 

SIDENOTE: When URLs change, services SHOULD redirect clients to the new location w/ a 301 (Moved Permanently) and the client SHOULD update it's "memory" for future use. We see this all the time on websites and APIs can do the same. When services fail to advise the client of the permanent change (or the client ignores the advice) clients will continue to try the old address and may eventually get a 404. Humans see this somethings on the web, too. And we them "go back" to some memorized address and look for the link that is identified as "payments" -- and clients can do the same.

Hope this helps.

SHAMELESS PLUG: Check out the book "RESTful Web APIs" for some background and examples on writing services to support hypermedia. I am also completing a new book ("RESTful Web Clients") that covers the challenge of writing client apps that consume hypermedia.




--
You received this message because you are subscribed to the Google Groups "Hypermedia Web" group.
To unsubscribe from this group and stop receiving emails from it, send an email to hypermedia-web+unsubscribe@googlegroups.com.
To post to this group, send email to hypermedia-web@googlegroups.com.
Visit this group at https://groups.google.com/group/hypermedia-web.
For more options, visit https://groups.google.com/d/optout.

Julian Everett

unread,
Sep 14, 2016, 5:38:30 AM9/14/16
to hyperme...@googlegroups.com
Hi Fabian,

I'd also think about your traditional API example.

GET myapi.com/payments/123/items/3

Where are you getting the values of '123' and '3' from? My guess is you are doing a database lookup or reading off a queue somewhere. So you are already starting with a lookup. If that lookup was brokered via your API then it could return the URI of the resource rather than just the entity IDs, decoupling the client from the URL template. As a result, to evaluate the alternatives you need to consider the full set of system interactions required to implement your use case, not just those which are currently mediated via some kind of web API.

Also on a domain modelling side note, I would double check that items are really the children of payments rather than orders in your business context. Typically items would be children of orders, and orders would have one of more associated payments. If you get the domain model wrong, that is definitely going to cause you pain with resource identification...

cheers

Julian


To post to this group, send email to hyperme...@googlegroups.com.

Fabian Ockenfels

unread,
Sep 14, 2016, 8:31:09 AM9/14/16
to Hypermedia Web
Thanks for the answers! I do realize that hypermedia is more than just a bunch of links, but this is what my original question is focussing on.
The quick example isn't a real project, so it may not be ideal. It could just as well be myapi.com/orders/123/items/3 or even myapi.com/a/123/b/3.

I wouldn't necessarily need a database lookup for this type of thing. Imagine a tightly coupled Rails server and an Ember client, both following the same URL pattern. Some user accessing the Ember client bookmarks the address myclient.com/a/123/b/3. When, at a later point in time, he opens this bookmark, I could immediately pass that request through to myapi.com/a/123/b/3.

The way I currently see it, this would not be possible in a hypermedia client, because nobody guarantees me that this URL structure still exists.
Basically my question boils down to this: How do I enter my API at a point that isn't the root? It's not possible, is it?
To unsubscribe from this group and stop receiving emails from it, send an email to hypermedia-we...@googlegroups.com.

To post to this group, send email to hyperme...@googlegroups.com.
Visit this group at https://groups.google.com/group/hypermedia-web.
For more options, visit https://groups.google.com/d/optout.

--
You received this message because you are subscribed to the Google Groups "Hypermedia Web" group.
To unsubscribe from this group and stop receiving emails from it, send an email to hypermedia-we...@googlegroups.com.

mca

unread,
Sep 14, 2016, 8:52:49 AM9/14/16
to hyperme...@googlegroups.com
<snip>
Basically my question boils down to this: How do I enter my API at a point that isn't the root? It's not possible, is it?
</snip>
of course, it's possible. I even walked through an example of it. 

I suspect your question is not "is it possible?" but is instead you are asking "can anyone guarantee me that a URL will ALWAYS be available FOREVER?" and, of course, the answer is "No" and it always has been "No."

Hypermedia clients, like everything/everyone else in the world have, no control over how servers manage their URLs.

However, breaking clients is not a REQUIREMENT. server developers can act responsibly. For example:
- service providers can promise to NOT change URLs
- service providers can provide 301 responses when URLs change
- service providers can include metadata on URLs to help clients know whether the URL is assured not to change (HAL has "deprecated=true", I've used "assured=true")

and, of course, clients can watch for, and honor, these types of things.

Cheers.
To unsubscribe from this group and stop receiving emails from it, send an email to hypermedia-web+unsubscribe@googlegroups.com.
To post to this group, send email to hypermedia-web@googlegroups.com.

Fabian Ockenfels

unread,
Sep 14, 2016, 9:25:44 AM9/14/16
to Hypermedia Web
I'm slowly beginning to understand your example. At least I hope so.

So a user works with my client app. When a new URL is discovered I store it. Presumably in local storage.
The next time said user requires this data I can retrieve the URL from local storage and use it directly.
If the API request returns a 301 response, I discard the URL and start at the top.

mca

unread,
Sep 14, 2016, 9:34:03 AM9/14/16
to hyperme...@googlegroups.com
if the service returns HTTP 301 (permanently moved), it is also returning the new URL. the client SHOULD be able to use that new URL (and store it for future use) and never bother the human/user about it.

if the service returns HTP 302 (temporarily moved), it is also returning the temporary URL. the client SHOULD be able to use the provided URL and SHOULD NOT store it for future use -- all without bothering the human/user about it.

if the service returns 404, then the client app needs to: 
- alert the human and let the human sort it out (stop here) or..
- go to some other existing URL (starting URL is proly the best guarantee) and work out how to get to where they want to go. 

this "work out how to get..." is no trivial matter. humans use lots of "smart guessing" to solve this on the Web w/ a browser. getting an API client to do this on it's own is tricky. I use a pattern (not a standard) in my machine apps to always return a link marked "index" (<a href="..." class="index" />) which will return all the possible URLs (and their identifiers). the client can then use this response to scan for the link it was originally looking for (e.g. "what is the 'payments' URL now?") and then use the found link (and storing it for future use).

hope this helps.

cheers.



To unsubscribe from this group and stop receiving emails from it, send an email to hypermedia-web+unsubscribe@googlegroups.com.
To post to this group, send email to hypermedia-web@googlegroups.com.

Fabian Ockenfels

unread,
Sep 14, 2016, 9:38:43 AM9/14/16
to Hypermedia Web
That helped a lot. Kudos!

mca

unread,
Sep 14, 2016, 9:41:55 AM9/14/16
to hyperme...@googlegroups.com
cool.

would love to hear about what you're working on and how it goes.

feel free to continue to post here w/ Qs/comments/observations.

cheers.

To unsubscribe from this group and stop receiving emails from it, send an email to hypermedia-web+unsubscribe@googlegroups.com.
To post to this group, send email to hypermedia-web@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages