Introduction à
HATEOAS

Human Talks Montpellier - Mai 2013

Jérémy Barthe


Web developer

HATEOAS
késako ??!!

Pour commencer on va parler d'API
et plus précisemment d'API REST !

REST (REpresentational State Transfer)

est un style d’architecture pour les systèmes hypermédia distribués.
Ce style d'architecture est particulièrement bien adapté au World Wide Web...
Source : wikipédia

Pour résumer, une API REST expose une collection de ressources et permet d'agir dessus.

Les 3 étapes vers REST

Level 0
  • Communication client / serveur via le protocole HTTP
  • 1 URL / 1 type de verbe HTTP (en général POST)
Level 1: Resources
  • Plusieurs URLs / orientées ressources
  • toujours 1 seul verbe HTTP (en général POST)
Level 2: HTTP Verbs
  • Verbe HTTP (GET, POST, PUT, DELETE)
  • Status code HTTP
Level 3: Hypermedia Controls
  • autrement appelé HATEOAS, mais patience...

Source : Richardson Maturity Model

Cas pratique

création d'une API REST pour le site des Human Talks
Contexte : API publique

Description de l'API

GET: /events.(xml|json)
Liste tous les événements
GET: /cities/montpellier/events.(xml|json)
Liste les événements de Montpellier
GET: /cities/montpellier/events/31.(xml|json)
Affiche les détails de l'événement 31 de Montpellier
GET: /talks.(xml|json)
Affiche tous les talks
GET: /events/31/talks.(xml|json)
Affiche les talks de l'événement 31
POST: /talks.(xml|json)
Proposer un talk

GET: /events.xml

HTTP/1.1 200 OK
Content-Type: text/xml; charset=utf-8

<?xml version="1.0" encoding="utf-8" ?>
<events>
    <event>
        <id>29</id>
        <city>Paris</city>
        <date>2013-04-09T19:00:00Z</date>
    </event>
    ...
    <event>
        <id>1</id>
        <city>Montpellier</city>
        <date>2012-07-10T19:00:00Z</date>
    </event>
</events>
                        

GET: /events/1/talks.xml

HTTP/1.1 200 OK
Content-Type: text/xml; charset=utf-8

<?xml version="1.0" encoding="utf-8" ?>
<talks>
    <talk>
        <id>1</id>
        <event>1</event>
        <title>Impress(.js) everybody !</title>
        <speaker>Julien Bordellier</speaker>
        <description>Présentation et introduction à Impress.js (en impress.js)</description>
        <slides>http://perso.epitech.eu/~bordel_j/humantalks/</slides>
    </talk>
    ...
    <talk>
        <id>4</id>
        <event>1</event>
        <title>Pourquoi choisir le framework AngularJS</title>
        <speaker>Thierry Chatel</speaker>
        <description>Un aperçu rapide des principaux atouts du framework JavaScript AngularJS...</description>
        <slides>http://www.methotic.com/ressources/20120710-humantalk-angularjs/</slides>
    </talk>
</talks>
                        

Constat : notre API n'est pas RESTful

car nous ne respectons pas le niveau 3 :
Hypermedia Controls

HATEOAS
Hypermedia As the Engine Of Application State

Expose en plus de l'état, les actions / transitions possibles autour de l'objet au travers de liens hypermédias.

Navigation dynamique dans l'API en fonction de l'état de chaque ressource affichée.


Les plus :

  • implémentation découplée
  • plus besoin de manipuler les URLs
  • forme d'auto-documentation de l’API

GET: /events.xml

HTTP/1.1 200 OK
Content-Type: text/xml; charset=utf-8

<?xml version="1.0" encoding="utf-8" ?>
<events>
    <event>
        <id>29</id>
        <city>Paris</city>
        <date>2013-04-09T19:00:00Z</date>
        <link rel="self"  href="/events.xml" />
        <link rel="city"  href="/cities/paris/events.xml" />
        <link rel="event" href="/cities/paris/events/29.xml" />
        <link rel="talks" href="/events/29/talks.xml" />
    </event>
    ...
</events>
                        

GET: /events/1/talks.xml

HTTP/1.1 200 OK
Content-Type: text/xml; charset=utf-8

<?xml version="1.0" encoding="utf-8" ?>
<talks>
    <talk>
        <id>4</id>
        <event>1</event>
        <title>Pourquoi choisir le framework AngularJS</title>
        <speaker>Thierry Chatel</speaker>
        <description>...</description>
        <slides>...</slides>
        <link rel="self"   href="/events/1/talks.xml" />
        <link rel="event"  href="/cities/montpellier/events/1.xml" />
        <link rel="talks"  href="/events/1/talks.xml" />
        <link rel="city"   href="/cities/montpellier/events.xml" />
        <link rel="slides" href="http://www.methotic.com/..." />
    </talk>
    ...
</talks>
                        

Et une homepage !

GET: /index.xml

HTTP/1.1 200 OK
Content-Type: text/xml; charset=utf-8

<?xml version="1.0" encoding="utf-8" ?>
<links>
    <link rel="events" href="/events.xml" />
    <link rel="talks"  href="/talks.xml" />
    <cities>
        <link rel="montpellier" href="/cities/montpellier/events.xml" />
        <link rel="paris"       href="/cities/paris/events.xml" />
    </cities>
</links>
                        

On n'a parlé d'API...
mais toujours pas de JSON ?!

Problème : aucun standard pour afficher des hypermédias.

Exemple Collection+JSON


{ "collection" :
    {
        "version" : "1.0",
        "href" : "http://example.org/friends/",

        "links" : [
            {"rel" : "feed", "href" : "http://example.org/friends/rss"},
            {"rel" : "queries", "href" : "http://example.org/friends/?queries"},
            {"rel" : "template", "href" : "http://example.org/friends/?template"}
        ]
    }
}
                        

Exemple HAL


{
    "_links": {
        "self": { "href": "/orders" },
        "next": { "href": "/orders?page=2" },
        "find": { "href": "/orders{?id}", "templated": true },
        "admin": [
            { "href": "/admins/2", "title": "Fred" },
            { "href": "/admins/5", "title": "Kate" }
        ]
    }
}
                        

Conclusion

quelques problèmes

  • naviguer dans une API comme un client pose un problème d'accés aux ressources en un minimum de click ;
  • les hypermédias alourdissent un peu la réponse (peut être problématique dans le contexte d'une application mobile) ;
  • HATEOAS ou hypermedia API repose autour d'un concept mais de nombreuses implémentations sont possibles...

mais surtout...

For an API to be HATEOAS-compliant it requires a client app that is also HATEOAS-compliant...
Source : slides Apigee

Questions ?

Quelques liens

 

Exemples d'API