UPMC NI584-2008nov c C.Queinnec 3/21 UPMC NI584-2008nov c C.Queinnec 4/21 Plan Architecture des Applications Réticulaires Id : cours3.bk 65 2008-11-30 09 :43 :26Z queinnec Christian Queinnec Université Paris 6 Deuxième vague 2008-2009 1 Principes Architecture 2 Perl Java 3 Conclusions UPMC NI584-2008nov c C.Queinnec 2/21 Exemple : Amazon S3 Pourquoi ne pas s appuyer plus sur HTTP? Thèse de Roy Fielding (2000) Architectural Styles and the Desing of Network-Based Software Architectures Plus de sémantique dans l URL : toute ressource manipulable a une URI propre Pas d enveloppes (aller ou retour) : l URL est l enveloppe d émission. Outre GET, usage des commandes HEAD, POST, PUT, DELETE Pour l instant pas d équivalent à WSDL mais WADL? Les grands exemples d architecture REST : Amazon, Google,... mais aussi Atom, Ruby on Rails Serveur programmatique de stockage GET /bucket liste les objets contenus dans une aire GET /bucket/object renvoie l objet HEAD /bucket/object ne renvoie que les méta-données concernant l objet PUT /bucket/object + body crée/modifie l objet POST /bucket + body crée un objet anonyme et renvoie son URI (via Location) DELETE /bucket/object supprime l objet DELETE /bucket supprime l aire...
UPMC NI584-2008nov c C.Queinnec 7/21 UPMC NI584-2008nov c C.Queinnec 8/21 Principes REST Rappels d HTTP Nommage Toute URI désigne une unique ressource. mais une même ressource peut (temporairement ou non) avoir plusieurs noms. Par exemple /software/1.0.3.tgz ou /software/latest.tgz Représentations de ressources dans l URI dans les entêtes HTTP : Accept, Accept-Language, Accept-Encoding etc. Conséquences d HTTP : pas d état, sémantique des commandes fixée CRUD = POST, GET, PUT, DELETE Soucis : GET, HEAD sont (doivent être) sans effet secondaire (donc cachables, supportant If-Modified-Since, ETags, Expires,... ) PUT, DELETE sont (doivent être) idempotents les navigateurs ne savent en général émettre que GET et POST! Mais HTML5 corrige cela (sinon X-HTTP-Method-Override) pourquoi inventer d autres commandes (WebDAV : MOVE, COPY, SEARCH,... )? UPMC NI584-2008nov c C.Queinnec 5/21 Codes d HTTP UPMC NI584-2008nov c C.Queinnec 6/21 Architecture d une application REST 200 OK 201 Created (+ Location pour URI canonique) 202 Accepted (+ Location pour URI de contrôle) 204 No Content (la représentation est vide) 301 Moved Permanently (+ Location) 303 See Other (+ Location pour le contenu de la réponse) 304 Not Modified 307 Temporary Redirect (+ Location pour re-soumettre la requête) 400 Bad Request 404 Not Found 405 Method Not Allowed 406 Not Acceptable (pas de représentation acceptable) 409 Conflict 410 Gone 415 Unsupported Media Type 500 Internal Server Error 503 Service Unavailable L URI est analysée pour déterminer la ressource concernée. pour S3 : /{bucket/{object la commande est déterminée (GET, PUT, POST, DELETE) Si retour il y a, la représentation de la ressource ou de l anomalie est déterminée les méta-données décrivant la représentation accompagnent celle-ci.
UPMC NI584-2008nov c C.Queinnec 11/21 UPMC NI584-2008nov c C.Queinnec 12/21 Architecture usuelle Soucis La forme usuelle est d avoir une arborescence de contrôleurs/actions : (methode patronurl) (variablespatronurl ressource) Par exemple (en omettant l accès à la requête pour obtenir les paramètres HTTP additionnels) : GET / person /{ nom /{ prenom - > function ( nom prenom ) ressource PUT / person /{ id / age /{ age -> function (id age ) ressource Multiples variantes différemment Curryfiées ou empaquetées : / person /{ nom / age /{ age -> function (% parametres ) - > GET - > ressource actions binaires : exprimer qu une personne va à une réunion? transactionnel décrire un virement bancaire? sécurité Les URI doivent-elles être évidentes ou opaques? résistance au changement : /person/23eab89c vis-à-vis de //www.systeme-lip6.fr/christian.queinnec/index.html (maintenant //lip6.fr/christian.queinnec/ UPMC NI584-2008nov c C.Queinnec 9/21 Comparaisons UPMC NI584-2008nov c C.Queinnec 10/21 SOAP est indépendant du transport donc d HTTP propre modèle de sécurité propre retour des erreurs propre stratégie de cache ou d idempotence WSDL définit finement les formats des données échangées En revanche, Rest est plutôt orienté vers l échange de documents (XML, micro-formats, PDF, JSON, etc.). Avec XML, notion de pièces jointes (comme en JBI Java Business Integration). Rest utilise des substantifs, les services utilisent plutôt des verbes. Perl : REST::Resource, REST::Application, Catalyst::Action::REST (par ordre d élaboration croissante) Java : Restlet Les moteurs REST peuvent fonctionner seuls ou être intégrés dans Apache ou Tomcat. Avec Apache, directive AcceptPathInfo utile
UPMC NI584-2008nov c C.Queinnec 15/21 UPMC NI584-2008nov c C.Queinnec 16/21 Perl REST : :Resource Perl REST : :Application 1 sous-classer REST::Resource 2 indiquer les fonctions à invoquer pour chaque méthode HTTP. Ces fonctions ont la signature (webapp requête)... 3 écrire ces fonctions qui construisent la réponse HTTP package My :: REST :: Resource ; use base " REST :: Resource "; sub new { my ( $class ) = @_; my $webapp = $class -> SUPER :: new (@_ ); $webapp -> method ( GET, \& getfunction, $comment ); sub getfunction { my ( $webapp, $request ) = @_;... UPMC NI584-2008nov c C.Queinnec 13/21 Perl Catalyst : :Action : :REST 1 sous-classer REST::Application 2 spécialiser setup() pour ajouter des couples URI-regexp fonction(webapp regexp-parts)... 3 écrire les fonctions prenant des morceaux de l URI (les informations supplémentaires sont dans la webapp et construisant la réponse HTTP my My :: REST :: Application ; use base REST :: Application ; sub setup { my ( $webapp ) = @_; $webapp - > resourcehooks ( m ^/ city /(\ w +)/ station /(\ d+)$ => \& stationfonc ); sub stationfonc { my ( $webapp, $city, $stationid ) = @_;... UPMC NI584-2008nov c C.Queinnec 14/21 ### in lib / MyApp.pm use Catalyst qw/- Debug /; # include plugins here as well % catalyst. pl MyApp % ### add models, views, controllers % script / myapp_create. pl model MyDatabase DBIC :: Schema \ > create = dynamic dbi : SQLite :/ path /to/db % script / myapp_create. pl view MyTemplate TT % script / myapp_create. pl controller Search % ### built in testserver % script / myapp_server. pl ### In lib / MyApp / Controller / Root.pm ( autocreated ) sub foo : Global { # called for / foo, / foo /1, / foo /1/2, e # args are qw /1 2/ for / foo /1/2 my ( $self, $c, @args ) = @_; $c -> stash - >{ template = foo.tt ; # set the template # lookup something from db # stash vars are passed to TT $c -> stash - >{ data = $c -> model ( Database :: Foo )-> search ({ country => $args [0] ); if ( $c ->req -> params - >{ bar ) { # access GET or POST parameters $c -> forward ( bar ); # process another action # do something else after forward returns
UPMC NI584-2008nov c C.Queinnec 19/21 UPMC NI584-2008nov c C.Queinnec 20/21 Java Restlet # The foo. tt TT template can use the stash data from # the database [% WHILE ( item = data. next ) %] [% item. foo %] [% END %] UPMC NI584-2008nov c C.Queinnec 17/21 Lire le tutoriel sur le site Restlet // Create a component Component component = new Component (); component. getservers (). add ( Protocol.HTTP, 8182); component. getclients (). add ( Protocol. FILE ); // Create an application Application application = new Application ( component. getcontext ()) { @Override public Restlet createroot () { // Create a root router Router router = new Router ( getcontext ()); // Attach a guard to secure access to the directory Guard guard = new Guard ( getcontext (), ChallengeScheme. HTTP_ BASIC, " Restlet tutorial "); guard. getsecrets (). put (" scott ", " tiger ". tochararray () router. attach ("/ docs /", guard ); UPMC NI584-2008nov c C.Queinnec 18/21 // Create a directory able to expose a hierarchy of files Directory directory = new Directory ( getcontext (), ROOT_URI ); guard. setnext ( directory ); // Create the account handler Restlet account = new Restlet () { @Override public void handle ( Request request, Response response ) { // Print the requested URI path String message = " Account of user \"" + request. getattributes (). get (" user ") + "\""; response. setentity ( message, MediaType. TEXT_PLAIN ); ; // Attach the handlers to the root router router. attach ("/ users /{ user ", account ); // Return the root router return router ; host = new VirtualHost ( getcontext ()); host. sethostdomain (" restlet. org restlet. net restlet. com " + " www. restlet. net www. restlet. com "); host. sethostport (" 80 " + Integer. tostring ( port )); host. attach ( new RedirectApplication ( getcontext (), " http :// www. restlet. org {rr", true )); gethosts (). add ( host ); // Attach the application to the component and start it component. getdefaulthost (). attach ( application ); component. start ();
Conclusions Conclusions REST est un style architectural. Structurant : à cause du nommage des URI Efficace : utilise bien la machinerie HTTP Évolutif : en termes de nouvelles URIs ou représentations Indépendant des mises en œuvre (jsp, restlet, etc.) UPMC NI584-2008nov c C.Queinnec 21/21