Accéder à des services web RestFul
c 'est quoi un «service web» des fonctionnalités d'une application exposées et accessibles à distance au travers d'une api construite au dessus de http (i.e. Avec des urls)
pourquoi faire des «services web» rendre l'application web programmable une app qui affiche des twits : accède à twitter déporter l'interface et l'interaction sur le client permet d'avoir plusieurs interfaces différentes : browser, android app, ios app combiner différents services/données pour former un mashup données + géolocalisation
GET index.php POST html serveur web api GET POST {données}
une api «service web» une api dédiée retourne des données dans un format exploitable par n'importe quelle application xml Json utilisée par des applications (et non un navigateur) Applications tierces Application mobile native (ios, Android..) Application serveur (php, java, ruby) ou client (js) facile d'emploi et d'utilisation par les programmeurs
json : javascript objet notation Format évaluable en javascript objet : { attribut1 : valeur1, attribut2 : valeur2 } tableau : [ valeur1, valeur2, valeur3..] valeur : un objet, un tableau, un littéral : ''chaine de caractères'', numérique null, true, false [ { ''nom'' : ''messi'', ''prenom'' : ''leo'', ''mail_a'' :''leo.messi@barca.net'' }, { ''nom'' : ''platini'', ''prenom'' : ''michel'', ''mail_a'' : ''mic.plat@uefa.net'' }, { ''nom'' : ''pelé'', ''prenom'' : ''pelé'', ''mail_a'' : ''pelé@fifa.net'' } ]
json & php json_encode( $v ) : encode le contenu de $v en format json produit une chaine de caractères représentant un tableau, un objet ou une valeur au format json json_decode( $json_string ) : décode la chaine json et renvoie une valeur php : un tableau un objet anonyme (pas de classe) une valeur
une api RESTFul Objectifs : simplicité, généralité, scalabilité Principe : faire des actions de base sur des ressources Une ressource : un objet, association, une exécution désignée par une uri : http://lunch.net/api/restos/125 Les actions : CRUD (create/retrieve/update/delete) Utilise les méthodes HTTP pour désigner les actions POST : create, GET : retrieve, PUT:update, DELETE
ressources de type «objets de l'application» Exemples : thèmes, restaurants, plats annonces, catégories, département produits, catégories, tarifs Pour 1 type de ressource : 2 URIs http://lunch.net/api/plats : liste des plats http://media.net/api/plats/122 : le plat d'id 122 Nommage des ressources : un nom + un id
exemple /api/themes/ /api/themes/42 /api/restos/ /api/restos/73 /api/plats/ /api/plats/1337
Actions sur les ressources METHOD /restos /restos/23 GET read Liste les restos Retourne le resto 23 POST create PUT update DELETE delete Crée un nouveau resto (les données sont dans le post) Met à jour la liste complète des restos Supprime la liste complète des restos ERREUR Met à jour le resto 23 (s'il existe, sinon erreur) Supprime le resto 23
GET /plats HTTP/1.1 host: www.media.net content-type: application/json GET /plats/3 HTTP/1.1 host: www.media.net content-type: application/json HTTP/1.1 200 OK content-type: application/json [ {. }, {. },. ] A PI POST /plat HTTP/1.1 host: www.media.net content-type: application/json nom=pizza&prix=8.0 HTTP/1.1 200 OK content-type: application/json { "id" :3, "nom" : "nems crevette",.. } HTTP/1.1 201 CREATED content-type: application/json R ES T Fu l
associations et actions sur les associations Une ressource objet peut-être liées à d'autres ressources : /themes/42/restos: les restos du theme 42 /plats/1337/restos: le resto du plat 1337 Limiter à 1 association /tarifs/3/produits/categories /ressource/identifiant/ressource
exemple /api/themes/42/restos /api/restos/73/theme /api/restos/73/plats /api/plats/1337/restos
Actions sur les associations METHOD GET read POST create PUT update DELETE delete /themes/42/restos Retourne la liste des restos du theme 42 Création d'une association entre un resto (existant) et le theme 42 Mise à jour la liste des restos du theme 42 Supprime toutes les associations entre le theme 42 et un resto
actions complexes Recherches : compléter les uris avec une query /plats?nom=pizza&prix=8 Réponses partielles : passer la liste des attributs attendus en paramètre /plats/345?fields=nom,prix pagination pour les grandes listes /plats?limit=25&offset=50 Positionner l'uri de la page suivante dans la réponse /ouvrages?limit=25&offset=75
les réponses 1 réponse REST = réponse HTTP status line + headers + content utilise un sous-ensemble des status HTTP 200 OK, 400 Bad Request, 500 Internal Server Error 201 Created, 304 Not Modified, 404 Not Found, 401 Unauthorized, 403 Forbidden utilise les headers : Content-type : application/json Content-type : application/xml contenu de la réponse : représentation de la ressource demandée
les cas d'erreurs status indiquant l'erreur + Content-type + un message «verbeux» dans la réponse, à destination des utilisateurs HTTP/1.1 404 NOT FOUND Content-type : application/json { ''usermessage'' : ''la ressource demandée n'a pas été trouvée ; Essayez avec une autre valeur, et faites plus attention à ce que vous faites!'', ''errorcode'' : ''123456'', ''infos'' : ''http://media.net/errors/123456'', ''devmessage'' : ''RTFM'' }
les réponses 200 Status + content-type + données formatées http://media.net/rest/adherents HTTP/1.1 200 OK Content-type : application/json [ ] {. }, {. }, {. }
le contenu des réponses : représentation des ressources Ressources uniques : renvoyer 1 objet json indique le type dans 1 attribut liste les champs/valeurs de la ressource champs média : indique une url
exemple https://webetu.iutnc.univ-lorraine.fr/www/canals5/crazylunch/plats/1 HTTP/1.1 200 OK Content-Length: 270 Content-Type: application/json; charset=utf-8 Date: Mon, 17 Feb 2014 13:59:57 GMT { "id": "1", "nom": "Classique", "description": "Tomate, Mozarella, Olives", "prix": "8", "photo": "pizza_classique.jpg", "id_resto": "1", "type": "plat", "imageuri": "/www/canals5/crazylunch/images/original/pizza_classique.jpg", "origin": "https://webetu.iutnc.univ-lorraine.fr" }
listes de ressources : 1 tableau json contenant des objets simplifiés, avec pour chacun une uri vers la ressource complète http://media.net/rest/livres?genre=polar HTTP/1.1 200 OK Content-type : application/json [ ] { "type" : "Livre", "id":53, "titre" : "le faucon de malte", "uri":"media.net/rest/livres/53" }, { "type" : "Livre", "id":56, "titre" : "mystic river", "uri":"media.net/rest/livres/56"}, { "type" : "Livre", "id":76, "titre" : "king suckerman", "uri":"media.net/rest/livres/76" }, { "type" : "Livre", "id":95, "titre" : "le poête", "uri":"media.net/rest/livres/95" },
interagir avec un service rest Client rest : doit forger des urls et exploiter les réponses Un navigateur ne peut pas le faire : Restreint à GET/POST Programmer un client Ligne de commande : curl js Php : curl Utiliser une classe ou un micro-framework php Pest, HTTPFul Guzzle
Client rest en curl $url = 'http://www.media.net '; $headers = array( 'user-agent' => '..', 'content-type'=>'..') ; $ch = curl_init($url); /* options */ curl_setopt($ch, CURLOPT_FRESH_CONNECT, true); curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); /* données */ curl_setopt($ch, CURLOPT_HTTPHEADER, $headers ) ; curl_setopt($ch, CURLOPT_POSTFIELDS, $fields ) ; // Récupération $page_content = curl_exec($ch); $http_response = curl_get_info($ch, CURLINFO_HTTP_CODE) ; $encode = curl_get_info( $CH, CURLINFO_CONTENT_TYPE) ; curl_close($ch); // Décoder Switch ( $encode ) {...
Client Rest avec Guzzle Forge les requêtes avec la méthode choisie Ajoute des headers Envoie Récupère et décode les données de retour Sait parler xml et json
utiliser Guzzle 1.Créer un client : $c = new Client($url) ; 2.Créer une requête $req = $c-> get($request_uri) // ->post(..) ->put(..) 3.Configuer la requête : options, paramètres du post $req->addpostfields( array ('ref'=>'rx0987','stock'=> 34)) ; $req->addpostfile('img_file', 'img/rx09.jpg', 'image/jpeg') ; 4.Envoyer la requête 1.$response = $req->send() ;
Les réponses le code de retour : $response -> getstatuscode() : les headers de la réponse : array : $response ->headers->toarray() ; raw : $response -> getrawheaders() ; le contenu raw : $response -> getbody() décodé : $response->json() ;
require 'vendor/autoload.php' ; use Guzzle\Http\Client ; $uri= 'https://webetu/www/canals5/crazylunch/' ; $client = new Client($uri) ; $request = $client->get( 'plats/' ) ; $response = $request->send() ; echo "response status: ". $response->getstatuscode(). "<br />"; foreach ($response->getheaders()->toarray() as $head=>$val) { echo "$head: ''. $val[0]. ''<br/>"; } // $response->body : tableau d'objets foreach ($response->json() as $p) { echo "<p>id : ".$p['id']. "reference : ". $p['ref']."<br />"; echo "<img src=\"". $p['imgurl']."\" alt=\"\"> <hr/></p>"; }B
Installer Guzzle Utiliser composer : gestionnaire de packages pour php Créer un fichier composer.json décrivant les packages utilisés par le projet : Installer : >php composer.phar install >composer install // si composer est installé dans bin Télécharge le code dans le répertoire./vendor Crée un autoloader { } "require": { "guzzle/guzzle" : "~3.8", "php" : ">=5.3.3" }