REST in practice

How to design flexible and
discoverable interfaces using HAL
and Web API
Ian Brennan, Application Archit...
ezetop

• Market leader in international and online top
up
– Wholesale, retail, consumer
– Integrated, online, mobile apps...
Core Principles of REST based APIs
HATEOAS
Hypertext as the engine of application state

• Navigable
– Your client works t...
REST ≠ RPC (even with JSON!)

REST

RPC

• Client follows the
relationship between
resources
• Client uses a URI
template ...
Some signs you aren't RESTful

Client code Builds URLs
Client code constructs query strings
Most of your methods use POST
...
Why bother?

• Flexible
–
–
–
–

Easy to extend
Easy to version
Built in service locator
Server side control of client sid...
Designing a REST interface
• “Resource first” - Similar in nature to an ERD
HAL – Hypertext Application Language

• JSON based
– Resources
– Links
– Embeds

http://tools.ietf.org/html/draft-kelly-js...
A Car, HAL style

{
"wheels": 4,
"doors": 5,
"_links": {
"self": {
"href": "http://example.com/car/1234-535"
}
}
Restrictions of HAL

• There is always a single resource delivered in
the body of a single request
– You can use embeds to...
More useful relationships

{
"wheels": 4,
"doors": 5,
"_links": {
"self": {
"href": "http://example.com/car/1234-535"
},
"...
Two Cars, HAL style
{
"count": 2,
"_links": {
"self": {
"href": "http://example.com/car?owner=someone"
}
},
"_embedded": {...
The HAL Browser

• JQuery
based
• Browse any
HAL API
HAL Alternatives

• AtomPub/Collection+JSON
– Oldest hypermedia implementation
– Strong query support
– Strong collection ...
What’s in a link?

Better living through good
relationships
Standard Relationships
http://www.iana.org/assignments/link-relations/link-relations.xhtml

•
•
•
•
•
•
•

self
item
edit
...
Custom Relationships

• Non-IANA relationships should be URIs
• Curies make this readable
"_links": {
"self": {
"href": "/...
You reach everything by navigating
relationships
client
.Home("/car")
.Follow("veh:wheel")
.Follow("veh:tyre");

Car

veh:...
We can optimize using embeds...

client
.Home("/car")
.Follow("veh:wheel")
.Follow("veh:tyre");
Car

veh:wheel

veh:wheel
...
...as much as we like

client
.Home("/car")
.Follow("veh:wheel")
.Follow("veh:tyre");
Car

veh:wheel

veh:wheel

veh:wheel...
Hypertext Cache Pattern

client
.Home("/car")
.Follow("veh:wheel")
.Follow("veh:tyre");

• A well written client does not ...
One to many?
Intermediate grouping
resource

Link directly
•

Works fine if we know there

client strictly bounded
are
qua...
Linked items or embedded items?

• In ezetop our framework embeds collection
items within pages
• We sometimes link them t...
URI Templates

http://www.com/car?p={pageNumber}&s={pageSize}
• RFC6570
– Uri that allows value substitution
– Simple valu...
Caching
• HATEOS interfaces tend to be very chatty
– Caching is essential

• HTTP caching mechanisms
– Cache-Control heade...
CacheCow.Client

• Fully functional cache for .NET apps that use
HttpClient
– It decorates HttpClientHandler with caching
...
Simple Caching

Resource<Product>

• Time Based
– Cache-Control headers
– Just like a browser cache

Server

200 OK
MaxAge...
What’s an eTag?

• An eTag in an HTTP response defines a
version of a delivered resource
• Browser automatically asks if t...
ETag Caching with CacheCow.Server
• Content based
• eTag Hash generated
from resource and
URI
• Explicit clearing
supporte...
Consuming REST APIs

• Your client needs to be able to
–
–
–
–
–

Navigate relationships
Parse URI templates
Understand em...
REST in ezetop

• We have started to adopt HATAEOS
– August 2013

• All new services are fully RESTful
• Older services ar...
What we like








Easy to write services
Flexible (not WCF!)
Stateless
Platform independent
Standard
“API First”
What we don’t

Learning curve
Too much boilerplate in server code
Contract is not fully self documenting
Chattiness
Dealin...
“I wouldn’t start from here...”

• What is the correct home page for a
particular API?
– /api/ with all versions available...
“Is that the best way to get there?”

• Choosing the best navigation path is nonobvious
– Iterate early on the design

• A...
“Do you even know the way yourself?”

• It’s tough to generate fully qualified URIs
– Dev/staging/production scenarios
– “...
Naming is hard, part 1001

• HAL is non-prescriptive on relationships
– Relationship name is relatively anaemic
– Siren is...
“Why won’t you do what you’re told?”

• Clients can simply ignore RESTful semantics
– Parse URIs and use them to build a n...
“Just let me GET that for you...”

• Proxy patterns are bad in REST
– We can’t cache Product!

• Need to avoid this anti-p...
The problem with layer cakes
Gateway

Gateway

Topup
Gateway

Cheap
Calls

Ordering API

Mobile API

Mobile App

Payments
The alternative is to spread it around!

Cheap
Calls

Payments

Topup

Gateway

Gateway
Ordering API

Gateway

Mobile App
Library Support
• Libraries are available for both HAL and URI
templates in most languages
• Ruby, Python, Javascript, PHP...
HAL in Web API

• Not a 100% natural fit
– but working for us

• You need to return Hal resources instead of
“raw” models
...
Final thoughts

•
•
•
•

REST is 100% pull/poll
Emphasis is on flexibility
Good caching strategies are vital
Encourages a ...
Further Research

• REST

– “REST in Practice” book
– http://chimera.labs.oreilly.com/books/1234000001708/in
dex.html

• U...
Thanks for listening!

@ianbru
http://ie.linkedin.com/in/ianbrennan/
http://www.slideshare.net/IanBrennan1
Upcoming SlideShare
Loading in...5
×

Rest in practice

845

Published on

How to design flexible and discoverable interfaces using HAL and Web API

Published in: Technology
0 Comments
1 Like
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
845
On Slideshare
0
From Embeds
0
Number of Embeds
3
Actions
Shares
0
Downloads
6
Comments
0
Likes
1
Embeds 0
No embeds

No notes for slide
  • An eTag in an HTTP response defines a version of a delivered resourceClient asks if that version still valid (If-None-Match)Server says yes (304 Not Modified)Client uses it’s cached versionServer does not have to re-generate resource
  • The resulting interaction required a lot of URI trickery to get the right information..
  • Invest in better strategies?
  • Rest in practice

    1. 1. REST in practice How to design flexible and discoverable interfaces using HAL and Web API Ian Brennan, Application Architect, ezetop
    2. 2. ezetop • Market leader in international and online top up – Wholesale, retail, consumer – Integrated, online, mobile apps, responsive • 8 years building APIs – We have over 10 different APIs that allow you to top up a mobile phone • Challenge – Maintain compatibility with existing business – Implement new features – Move, divide, coalesce and transform existing services
    3. 3. Core Principles of REST based APIs HATEOAS Hypertext as the engine of application state • Navigable – Your client works the way that a browser does – Ideally, the client only constructs a single URL • Resource Driven – This is a “document driven architecture” rather than a “service oriented architecture” • HTTP-Centric – GET, PUT, POST, DELETE – Cache headers, eTags, redirects, locations
    4. 4. REST ≠ RPC (even with JSON!) REST RPC • Client follows the relationship between resources • Client uses a URI template to build a query. • Server delivers linking information between resources • Our contract is resource types, and relationship types. • Client knows the URL of each method • Client constructs query string parameter to build a query. • Client copies data between many models • Our contract is endpoint URIs, request types, and reply types.
    5. 5. Some signs you aren't RESTful Client code Builds URLs Client code constructs query strings Most of your methods use POST A proliferation of “request” and “response” classes • A proliferation of model classes • Deeply nested models • • • •
    6. 6. Why bother? • Flexible – – – – Easy to extend Easy to version Built in service locator Server side control of client side behaviour • Easy to cache – Server can control and drive caching behaviour – Standard, well understood caching model
    7. 7. Designing a REST interface • “Resource first” - Similar in nature to an ERD
    8. 8. HAL – Hypertext Application Language • JSON based – Resources – Links – Embeds http://tools.ietf.org/html/draft-kelly-json-hal
    9. 9. A Car, HAL style { "wheels": 4, "doors": 5, "_links": { "self": { "href": "http://example.com/car/1234-535" } }
    10. 10. Restrictions of HAL • There is always a single resource delivered in the body of a single request – You can use embeds to send related resources • All resources must have a “self” relationship – If it doesn’t have a URI, it isn’t a resource!
    11. 11. More useful relationships { "wheels": 4, "doors": 5, "_links": { "self": { "href": "http://example.com/car/1234-535" }, "journey-add": { "href": "http://example.com/journey?car=1234-535" }, "owner-query": { "href": "http://example.com/owner/someone" }, “change-wheel": { "href": "http://example.com/wheels/change?wheel={wheelNumber}" } }
    12. 12. Two Cars, HAL style { "count": 2, "_links": { "self": { "href": "http://example.com/car?owner=someone" } }, "_embedded": { "item": [ { "wheels": 4, "doors": 5, "_links": { "self": { "href": "http://example.com/car/1234-535" } } }, { "wheels": 4, "doors": 5, "_links": { "self": { "href": "http://example.com/car/1234-5356" } } }]}}
    13. 13. The HAL Browser • JQuery based • Browse any HAL API
    14. 14. HAL Alternatives • AtomPub/Collection+JSON – Oldest hypermedia implementation – Strong query support – Strong collection support • Siren – Invests more in describing relationships – More discoverable as a result – Strong validation semantics • So why HAL? – Simple, unobtrusive – Wide library support – Human readable
    15. 15. What’s in a link? Better living through good relationships
    16. 16. Standard Relationships http://www.iana.org/assignments/link-relations/link-relations.xhtml • • • • • • • self item edit next last profile curie List is quite arbitrary – there is no: • delete • add Mostly because these are done through verbs (but then why have edit?)
    17. 17. Custom Relationships • Non-IANA relationships should be URIs • Curies make this readable "_links": { "self": { "href": "/api/provider/Auris" }, "curies": { "href": "http://schema.ezetop.com/ild/{rel}", "name": "ild", "templated": true }, "ild:product-query": { "href": "/api/product?provider=Auris" } }
    18. 18. You reach everything by navigating relationships client .Home("/car") .Follow("veh:wheel") .Follow("veh:tyre"); Car veh:wheel veh:wheel veh:wheel Wheel Wheel Wheel veh:tyre veh:tyre veh:tyre Tyre Tyre Tyre 7 network requests! Highly cacheable
    19. 19. We can optimize using embeds... client .Home("/car") .Follow("veh:wheel") .Follow("veh:tyre"); Car veh:wheel veh:wheel veh:wheel Wheel Wheel Wheel veh:tyre veh:tyre veh:tyre Tyre Tyre Tyre 4 Network Requests Caching Moderate
    20. 20. ...as much as we like client .Home("/car") .Follow("veh:wheel") .Follow("veh:tyre"); Car veh:wheel veh:wheel veh:wheel Wheel Wheel Wheel veh:tyre veh:tyre veh:tyre Tyre Tyre Tyre 1 Network Request Caching Awful
    21. 21. Hypertext Cache Pattern client .Home("/car") .Follow("veh:wheel") .Follow("veh:tyre"); • A well written client does not care if it’s a link or an embed • Treats embeds as if they were GET requests • Optimization becomes a server side concern
    22. 22. One to many? Intermediate grouping resource Link directly • Works fine if we know there client strictly bounded are quantities .Home("/car") .Follow("veh:wheel"); • client Better for queries • Can support paging .Home("/catalog") .Follow(“shop:product-query") • Page resource open to extension .Follow(“item”); Catalog Car shop:product-query Page<Product> veh:wheel item Wheel Wheel Wheel Product Product Product
    23. 23. Linked items or embedded items? • In ezetop our framework embeds collection items within pages • We sometimes link them too Page<Product> Page<Product> item item Product Product Product Product Product Product
    24. 24. URI Templates http://www.com/car?p={pageNumber}&s={pageSize} • RFC6570 – Uri that allows value substitution – Simple values, but also lists and dictionaries – Not restricted to query strings • Implementations exist in most languages • Can be used in HAL LinkRelations – Link has "templated": true – Loosely coupled URI construction • Lightweight request types – Use sparingly!
    25. 25. Caching • HATEOS interfaces tend to be very chatty – Caching is essential • HTTP caching mechanisms – Cache-Control headers – eTags • Server controls the client cache – The server never caches content. client .Home(“http://ildserver") .Follow(“item”) .Follow(“ild:tenantproduct-by-tenant”) .Follow(“ild:account-by-consumerref”) .Follow(“ild:callernumber-query”) .Follow(“item”)
    26. 26. CacheCow.Client • Fully functional cache for .NET apps that use HttpClient – It decorates HttpClientHandler with caching semantics – Simple cache-control headers – Support for eTags also – Set it up through your IOC framework of choice • It has a pluggable store for cached resources – SQL Server, Memcached and you can build your own https://github.com/aliostad/CacheCow
    27. 27. Simple Caching Resource<Product> • Time Based – Cache-Control headers – Just like a browser cache Server 200 OK MaxAge: 10m GET Resource<Product> Cache Store Client
    28. 28. What’s an eTag? • An eTag in an HTTP response defines a version of a delivered resource • Browser automatically asks if that version still valid (If-None-Match) • Server says yes (304 Not Modified) • Client uses it’s cached version • Server does not have to re-generate resource • Built in support in all browsers
    29. 29. ETag Caching with CacheCow.Server • Content based • eTag Hash generated from resource and URI • Explicit clearing supported • Entity Tag Store Resource<Product> Entity Tag Store Product tag 200 OK 304 Not-Modified ETag: xyz – Pluggable, but standard stores exist • Challenging to configure Server GET GET eTag: xzy Resource<Product> Cache Store Client
    30. 30. Consuming REST APIs • Your client needs to be able to – – – – – Navigate relationships Parse URI templates Understand embeds Support caching (including eTags) Implement the Hypertext cache pattern • HAL is easy – navigation is hard • Is HAL suitable for a public API? – Amazon do it, among others.
    31. 31. REST in ezetop • We have started to adopt HATAEOS – August 2013 • All new services are fully RESTful • Older services are – RPC-JSON – WCF • Gradual transition to – Hypermedia API – Flat structure • Toolset – Web API 4; CacheCow; Tavis.UrlTemplates;
    32. 32. What we like       Easy to write services Flexible (not WCF!) Stateless Platform independent Standard “API First”
    33. 33. What we don’t Learning curve Too much boilerplate in server code Contract is not fully self documenting Chattiness Dealing with collections of resources
    34. 34. “I wouldn’t start from here...” • What is the correct home page for a particular API? – /api/ with all versions available? – /api/1 • What should I hard code?
    35. 35. “Is that the best way to get there?” • Choosing the best navigation path is nonobvious – Iterate early on the design • Avoid client repetition • Avoid backtracking – Where possible!
    36. 36. “Do you even know the way yourself?” • It’s tough to generate fully qualified URIs – Dev/staging/production scenarios – “Sibling” APIs • Location pattern built in, but is not free. • Strong URI-generation strategies are vital
    37. 37. Naming is hard, part 1001 • HAL is non-prescriptive on relationships – Relationship name is relatively anaemic – Siren is better here • A good naming convention can help a lot – Your relationships define your contract
    38. 38. “Why won’t you do what you’re told?” • Clients can simply ignore RESTful semantics – Parse URIs and use them to build a new query string – Rebuild links from scratch instead of accepting them from the serving application – Use string-replace instead of templated URIs • Randomly mutate URIs? • Provide client libraries?
    39. 39. “Just let me GET that for you...” • Proxy patterns are bad in REST – We can’t cache Product! • Need to avoid this anti-pattern Web Site REST client Ordering System Catalog System Product TenantProduct ProductLimit ProductCode IldVersion ProductColor Product
    40. 40. The problem with layer cakes Gateway Gateway Topup Gateway Cheap Calls Ordering API Mobile API Mobile App Payments
    41. 41. The alternative is to spread it around! Cheap Calls Payments Topup Gateway Gateway Ordering API Gateway Mobile App
    42. 42. Library Support • Libraries are available for both HAL and URI templates in most languages • Ruby, Python, Javascript, PHP, C#, Java, Scala, Objective-C, Eiffel, Clojure, Go • Quality varies • Navigation semantics will likely not be covered • Hypertext cache pattern will likely not be covered https://github.com/mikekelly/hal_specification/wiki/Libraries https://code.google.com/p/uri-templates/wiki/Implementations
    43. 43. HAL in Web API • Not a 100% natural fit – but working for us • You need to return Hal resources instead of “raw” models – Inheritance or composition both work – We use composition (with generics) • There is room for improvement – Consider alternatives in green field projects
    44. 44. Final thoughts • • • • REST is 100% pull/poll Emphasis is on flexibility Good caching strategies are vital Encourages a “flat service” structure – but that requires good security • Works well for us as an enterprise architecture – however, it relies on good client code
    45. 45. Further Research • REST – “REST in Practice” book – http://chimera.labs.oreilly.com/books/1234000001708/in dex.html • URI Templates – http://tools.ietf.org/html/rfc6570 – https://code.google.com/p/uritemplates/wiki/Implementations – https://github.com/tavis-software/UriTemplates • HAL – http://stateless.co/hal_specification.html – http://tools.ietf.org/html/draft-kelly-json-hal • CacheCow – https://github.com/aliostad/CacheCow
    46. 46. Thanks for listening! @ianbru http://ie.linkedin.com/in/ianbrennan/ http://www.slideshare.net/IanBrennan1
    1. A particular slide catching your eye?

      Clipping is a handy way to collect important slides you want to go back to later.

    ×