Des liens qui dépendent de l'état
C'est là que HATEOAS devient vraiment utile : les liens ne décrivent pas seulement les ressources liées, mais aussi ce qu'on a le droit de faire maintenant.
La vie d'une commande
pending ──(30 s)──▶ preparing ──(2 min)──▶ ready ──▶ served
│
└──▶ cancelled (uniquement tant qu'elle est pending)
Juste après la commande :
{
"id": 42,
"status": "pending",
"cocktail": "Segfault Sunrise",
"_links": {
"self": {"href": "/v1/orders/42"},
"cancel": {"href": "/v1/orders/42", "method": "DELETE"},
"cocktail": {"href": "/v1/cocktails/3"}
}
}
30 secondes plus tard, le barman a commencé. Même requête :
{
"id": 42,
"status": "preparing",
"cocktail": "Segfault Sunrise",
"_links": {
"self": {"href": "/v1/orders/42"},
"cocktail": {"href": "/v1/cocktails/3"}
}
}
Le lien cancel a disparu. Le serveur ne dit pas « tu ne peux plus annuler parce que le statut est preparing » : il ne propose simplement plus l'action.
Faites l'essai : commandez un cocktail et interrogez la commande toutes les 10 secondes avec curl. Regardez le lien disparaître en direct.
Côté client : suivre les liens, pas les règles
Sans HATEOAS, le client doit connaître la règle métier :
# ❌ La règle est dupliquée dans le client
if order["status"] == "pending":
show_cancel_button()
Le jour où le bar autorise l'annulation pendant la préparation, il faut mettre à jour toutes les applications : web, mobile, caisse… Avec HATEOAS, le client se contente de regarder si le lien existe :
order = requests.get(urljoin(BASE, "/v1/orders/" + str(order_id)), headers=headers).json()
cancel = order["_links"].get("cancel")
if cancel:
print("Annulation possible")
requests.request(cancel["method"], urljoin(BASE, cancel["href"]), headers=headers)
else:
print("Trop tard, le shaker tourne déjà")
La règle n'existe qu'à un seul endroit : le serveur. Il peut la changer, tous les clients suivent.
Ça marche aussi pour les droits
Les liens peuvent dépendre de qui demande, pas seulement de l'état :
- un barman voit un lien
servesur les commandesready, un client non ; - l'auteur d'un avis voit un lien
delete, les autres non ; - un client authentifié voit un lien
ordersur un cocktail, un visiteur anonyme voit un lienregister.
Masquer un lien n'est pas une protection : le serveur doit toujours vérifier l'état et les droits quand l'action arrive. Un DELETE envoyé à la main sur une commande en préparation doit toujours répondre 409.