REST – Architecture Orientée Ressource
Au menu aujourd’hui, un sujet très tendance: REST. Abordé par le biais de l’Architecture Orienté Ressource (ou ROA: Resource Oriented Architecture), autrement dit, comment créer une architecture de service basé sur REST.
Définitions
Comme toujours, commençons par quelques définitions. Je vais les faire assez théorique sinon après, il ne me restera plus rien à dire 🙂
- SOA : Service Oriented Architecture : Architecture orientée service.
- ROA : une architecture SOA basée sur des services web RESTful au lieu des services web “lourd” comme les services web SOAP.
- Services web RESTful : services web qui adhèrent complètement aux concepts et aux standards REST (accéder une ressource dans un mode ‘service’).
- REST : Representational State Transfer.
- Ressource : notion de base de l’architecture REST, elle est définie par son URL. C’est ce à quoi on veut accéder. via l’URL. Un exemple de ressource est une news accessible via l’URL http://monsite.com/news/1
- Représentation : comme son nom l’indique, c’est la représentation d’une ressource. Par exemple, http://monsite.com/news/1 peut être une page HTML qui représente la ressource ‘news numéro 1’.
Le principe de REST
REST est un design pattern (ou patron de conception) pour l’implémentation de système connecté. Ce n’est ni une technologie ni un standard; c’est un type d’architecture pour l’exposition de ressources sur le web.
L’architecture RESTful adhères à plusieurs principes :
- Les requêtes sont client-serveur
- Les requêtes sont stateless (sans état).
- Clients et serveurs adhèrent à une interface uniforme. Toutes les ressources sont accédée via une interface générique: les méthodes HTTP: GET, POST, PUT, DELETE, HEAD ou OPTION.
- Les clients accèdent à des ressources nommées. le système comprend des ressources nommées en utilisant des URL, comme des URL HTTP (mais ne se limitant pas à des URL HTTP). Pour faire simple: une ressources est représentée par une URL.
Mise en œuvre
Définition d’une stratégie d’URL
Partie la plus importante d’une architecture REST, la stratégie de création des URL vers les ressources. Son importance vient du fait que les URL définissent les ressources. Et qu’un bonne stratégie dans la définition d’URL va simplifier l’utilisation des ressources dans un mode service.
Voici un exemple, tirée de best-practice autour de la définition des URL de ressources:
- Les éléments d’une URL sont séparé par des slashs ( ‘/’).
- Les éléments d’une URL vont du générique vers le spécifique (catégorie -> sous-catégorie -> produit).
- Les élément d’un même niveau (donc entre deux ‘/’) sont séparé par des virgule (‘,’) quand l’ordre des éléments à de l’importance, par les point-virgule (‘;’) sinon.
- Pas de verbe ou de nom d’opération dans l’URL.
- L’utilisation de paramètres de requête (?nom=toto par exemple) est utilisé uniquement en PUT ou POSt (pour la création d’une ressource donc).
A ceux-xi on peut ajouter d’autres conseil qui ne font pas partie réellement des standard d’utilisation de REST mais qui permettent de faciliter l’utilisation de REST en tant qu’architecture de services web
- Un numéro de version en début d’URL facilite la création de représentation différente pour une même ressource dans le temps (lors de l’évolution du service)
- la fin de l’URL peut contenir la langue et le type de représentation de la ressource .
- Un principe intéréssant, peut être aussi de grouper ses ressource dans des sortes de package, le premier élément de l’URL sera donc un nom de package (par exemple: catalogue, order, …)
Voici quelques exemples:
- GET http://host:port/catalogue/v1/telephone/htcdream.fr.html : ressource pour l’affichage en HTML de la fiche produit de l’HTC dream. C’est un service qui fait partie du package de service catalogue. On apprend aussi ici que l’HTC Dream fait partie de la catégorie téléphone.
- GET http://host:port/catalogue/v1/telephonne.fr.html : ressource pour l’affichage en HTML de la catégorie ‘téléphone’.
- GET http://host:port/news/v1/categories.fr.atom : affichage en flux ATOM de l’ensemble des catégories de news.
- GET http://host:port/news/v1/categories/eco.fr.fr : affichage de la catégorie économique des news.
- POST http://host:port/news/v1/categories/eco?name= »ma news »&content= »c’est la crise » : création d’une news de nom « ma news » avec le contenue « c’est la crise » dans la catégorie ‘eco’
Gestion de multiple représentation pour une ressource
En spécifiant une extension différente dans l’URL, on peut demander à notre application de services web des représentation différentes sur une ressource.
Voici un exemples de représentation utile qui peuvent être implémentée et une suggestion des extensions à utiliser:
- .html : représentation XHTML d’une ressource. Je conseil en plus l’utilisation des microformat, et l’intégration d’une CSS par défaut pour qu’elle soit directement testable. De mon avis c’est la représentation préférable.
- .fragment : Pareil que le ‘.html’ Mais sans CSS et sans les tags <head> et <body>. Très utilise pour l’intégration directe via ajax de fragement HTML.
- .json : Représentation JavaScript JSON. Pratique pour l’appel via Ajax, de plus en plus de framework gérant le JSON.
- .atom : flux RSS de type ATOM, conseillé pour les listes
- .txt : représentation texte pour des ressources très simple, ou des test basique
- .xml : la représentation XML a pour but l’intégration via des langages évolué, des flash ou du flex par exemple. Dans tout les cas où la ressource devra être parsé pour recréer un objet c’est celle qui sera choisie.
Lors de la définition de votre architecture orientée services, vous choisirez les types de représentation nécessaire (même si je vous conseil d’en utiliser le plus possible), n’oubliez pas que même si votre architecture supporte toutes ces extensions, vous pouvez les implémenter sur une ressource uniquement si cela est nécessaire. Toutes les ressources ne doivent pas obligatoirement implémenter toutes les représentation.
Mais pensez bien que si votre application est facilement testable, dans un browser par exemple grâce à des flux ATOM et des représentation HTML c’est un plus non négligeable. Je conseil donc l’utilisation de représentation ATOM pour les listes et HTML pour les ressources.
Pour faciliter le tests, liée le plus possible les ressources les unes entre les autres (une liste contient les liens vers les ressources qu’elle liste) et, par exemple, créer des flux ATOM de liste d’exemple de vos ressources (un flux ATOM à la racine qui liste tout les package de ressource et un flux ATOM pour chaque package qui liste une série d’exemple et votre application devient navigable facilement!)
Un catalogue de microformat
Les microformats ne font pas partie de la spécification REST et ne devrait peut-être pas pas être évoqué ici mais je pense qu’ils peuvent apporter un plus réel dans l’aspect service.
Un microformat HTML est un ensemble de tags HTML et de classes CSS qui permettent de définir un pattern réutilisable. Ainsi, à chaque fois qu’on veut représenter de manière HTML un objet, on utilise le même ensemble de classes CSS et tags HTML ce qui permet de standardiser vos représentation et de facilement reconnaître dans vos HTML tel ou tel objet.
Pour en savoir plus, c’est ici: http://microformats.org/. Ce site comprend des microformat utilisé de par le web et certain design pattern pour la création de vos propre microformats.
Un catalogue de microformat étant juste l’ensemble des microformats utilisé dans votre application (ou dans VOS applications). L’idéal étant bien sur de fournir aux clients de vos application le catalogue en question et les explications sur ce dernier.
Gestion des erreurs
Il est conseillé d’utiliser les erreurs standard HTTP. Donc, de retourner un statut différent du statu 200 pour toute requête menant à une erreur. Il existe de nombreux statut disponible dans la spécification HTTP, pour les erreurs il faut utiliser les statuts dans les plages suivantes: 400 plage pour les erreurs client, 500 plage pour les erreurs serveur.
Voici les erreurs que je vous conseil au minimum d’utiliser:
- 400: Bad Request: si la reqûete est mal formé (un élément manquand ou incorrecte dans l’URL)
- 401: Permission denied: vous n’avez pas la permission d’accéder à cette ressource via cette opération (uniquement si la ressource est sécurisée)
- 404: Not Found: pas de ressources à cette URL
- 500: Server Error: une erreur s’est produite sur le serveur lors de l’appel à la ressource (problème de base de données par exemple)
Implémentation
L’implémentation peut se faire avec de nombreux technologie et framework différent. Pour n’en citer que quelques un (principalement dan le monde Java, étant développeut Java):
- RoR : Ruby On Rails contient une implémentation REST
- Spring 3.0 : la future version de Spring contient une implémentation REST de sa couche MVC
- Jax-RS (JSR311) : la spécification Java pour les services web RESTFul: la version actuelle comporte de nombreux manque (représentation unique, sécurité, ..). Espérons que la future spécification 1.1 les comblera.
- Jersey : implémentation de référence de la JSR 311
- Restlet : pour moi un des framework JAVA les plus abouti et stable au niveau REST. C’est celui que j’ai choisit pour mettre en place chez mon client une application de services web RESTful
Pour plus d’info sur Restlet et pour un exemple d’implémentation d’une architecture ROA, venez lire l’article que j’ai écrit à ce sujet: Implémenter une architecture de service web RESTfull avec Restlet et son extention Spring
6 réflexions sur « REST – Architecture Orientée Ressource »
Bonjour,
Intéressant Post.
Utilisateur SOAP, j’aimerais passer à REST… et suis donc parti sur ce 1er exemple (1 getter et 1 setter en JAX-RS)…
@Path(« rest »)
public interface MyInterface
{
@GET
@Path(« value »)
public long getValue();
@PUT
@Path(« value »)
@Consumes(« application/xml »)
public void seValue(long value);
}
Question: pourquoi cette requête échoue-elle ??
PUT http://localhost:8080/myInterface/rest/value HTTP/1.1
Content-Type: application/xml
User-Agent: Jakarta Commons-HttpClient/3.1
Host: localhost:8080
Content-Length: 25
2000
=> 400 BAD REQUEST
Ce « Body… » est probablement mal formaté?… mais comment l’écrire Svp ??
Auriez-vous une idée de ce qui pose souci ?
Merci,
Cordialement.
Hello,
Meme (presque) 1 an après, l’article reste intéressant.
En particulier la suite sur restlet m’a bien intéressé, je suis en train de faire un poc Restlet !
Ceci dit, dt la logique RESTfull, j’ai un problème dans la stratégie des url. On dit qu’on accède à une ressource via son uri.
Ok si la ressource est unitaire : GET http://host:port/catalogue/v1/telephone/htcdream.fr.html
Si la ressource est une liste, pas de problème, la liste est une ressource comme une autre : GET http://host:port/catalogue/v1/news.html
Mais si on souhaite récupérer une ressource qui n’est qu’une partie de liste : par exemple les news qui ont moins de 10 jours : Comment ne pas passer d’arguments autres que l’url ? je ne peux pas créer une ressource pour toutes les requêtes possibles non ? comment ne passer des arguments uniquement dans le cas de PUT ??
Je ne sais pas si ma question est claire, en résumé, je ne comprend pas comment respecter dans tous les cas « L’utilisation de paramètres de requête (?nom=toto par exemple) est utilisé uniquement en PUT ou POSt (pour la création d’une ressource donc). »
Merci de ton article,
Ben
Hello,
Il y a plusieurs manière de faire:
http://host:port/catalogue/v1/news_last_10_days.html -> pas élégant et pas toujours pratique
http://host:port/catalogue/v1/news/latests.html -> la plus simple
http://host:port/catalogue/v1/news/05082010,25072010.html -> la plus élégante et ma préférée
http://host:port/catalogue/v1/05082010,25072010/news.html -> si c’est plus facile dans ce sens, mais me semble moins logique
… on peut trouver pleins de solution dans ce style
Bon courage,
Loïc
Ok, mais pour moi cela revient à créer autant de ressources que de listes possibles : lateste_news.html 05082010,25072010.html
Sais tu si Restlet sait faire ça ? (sans créer une ressource pour chaque requête possible bien sûr…).
Restlet peut se baser sur des patterns d’URL, donc on peut lui donner un pattern du type
http://host:port/catalogue/v1/news/{dateFrom},{dateTo}.html
et il matchera une seul ressource!