Archives du tag: api

Développement Web

Les services web RESTful

Les services web sont aujourd’hui au coeur du web et au coeur des applications connectées.

Pour cela, beaucoup de services et d’outils utilisent le modèle REST. Sur iOS, on peut notamment citer l’excellent framework AFNetworking permettant d’accéder aux services web et son prometteur petit frère AFIncrementalStore qui permet lui de synchroniser cache local et service distant.

Pour autant, comment un service web être réellement RESTful ?

Cette question est en suspend depuis quelques années. Au travers de cet article, amené à évoluer, je vais tâcher d’apporter quelques éléments de réponses.

REST : kézako ???

Déjà, qu’est-ce REST ?

C’est un modèle d’organisation de service web exploitant au maximum le protocole HTTP et les standards du web afin d’être aussi léger que performant.

Le principe est d’accéder à des ressources en suivant le modèle objet.

Définition du service web

Afin de définir les ressources du service web, il suffit d’accéder à la racine de l’API.

Par exemple :

{   "url": "https://api.monservice.com",   "resources": {     "cars": {       "url": "https://api.monservice.com/cars"     },     "accounts": {       "url": "https://api.monservice.com/accounts"     }   } }

 

URL des ressources

Les resources sont accessibles via des URL.

Par convention, on utilisera toujours le pluriel pour les collections. Et on utilisera toujours des noms pour identifier les ressources.

Par exemple :

/cars : ensemble de voitures

/cars/count : nombre total de voiture

/cars/12 : voiture « 12″

/cars/12/options : options disponibles pour la voiture « 12″

/cars_models : toutes les relations entre voiture et modèle (many to many)

Options d’affichage

Il est possible de passer des paramètres dans les URL.

Par convention, pour n’afficher que certains champs, on utilisera « fields » séparé par des virgules ».

/cars?fields=immatriculation,color : je veux seulement les champs « immatriculation » et « color »

Egalement, on peut filtrer les résultats sur certains champs en les passant en paramètres.

/cars?color=red : seulement les voitures rouges

/cars?model.name=volvo : seulement les voiture dont le nom du modèle est volvo (certains caractères n’ont volontairement pas été échappés)

Pagination

Certaines options peuvent être passées dans l’URL afin de gérer la pagination.

- offset : premier résultat affiché

- limit : nombre maximal de résultats par page

- until : date maximale de création

- since : date minimale de création

- since_id : identifiant le plus ancien

- max_id : identifiant le plus récent

Cela permet de gérer un chargement progressif de manière très fiable.

L’en-tête HTTP « Link », avec les liens et les options « rel » (« next », « previous ») permet également de paginer la réponse.

L’en-tête HTTP « X-Result-Count » permet d’avoir le nombre total de résultats.

Aussi, on peut utiliser « Content-Range ». Ex. « Content-Range: cars 0-20/2550″. Et l’en-tête en requête serait « Range: cars=0-20″.

Actions

Idéalement, une action est définie par un verbe. La méthode HTTP dépend d’une modification ou non du contenu de la ressource ciblée.

POST /cars/12/buy : acheter la voiture « 12″

GET /cars/search : rechercher une voiture

Les verbes HTTP

Pour les ressources, utilisez la méthodes CRUD (Create, Read, Update, Delete) .

POST /cars : ajouter une voiture (redirige vers la ressource créée)

GET /cars/12 : voir la voiture 12

HEAD /cars/12 : savoir si la voiture 12 existe (aucune ressource retournée)

PUT /cars/12 : mettre à jour intégralement la voiture 12 (redirige vers la ressource mise à jour)

PATCH /cars/12 : mettre à jour intégralement la voiture 12 (redirige vers la ressource mise à jour)

DELETE /cars/12 : supprimer la voiture 12

OPTIONS /cars : description des actions possibles sur les ressources de type « cars » (via l’en-tête Allow, access-control-allow-methods, access-control-allow-origin et une description explicite dans le corps)

Pour les actions, on utilise souvent GET.

Lorsque l’on utilise AJAX, sur les navigateurs web par exemple, on n’a pas accès à PUT ou DELETE.

Ce n’est pas un problème : passez le paramètre « _method » avec comme nom la méthode HTTP à utiliser. Si vous utilisez un framework comme par exemple Ruby on Rails, la méthode sera automatiquement gérée.

Format des données

Plusieurs formats peuvent être utilisés. Ils sont définis en priorité par l’extension de l’URL, mais également par le Content-Type ou le Accept de la réponse et/ou de la requête.

application/xml est le plus ancien.

application/json est le plus courant. Parfaitement adapté aux services web orientés REST.

application/x-www-form-urlencoded est utilisé lors d’envoi de données. Chaque clé correspondant à une propriété de l’objet.

multipart/form-data est lui particulièrement adapté pour l’envoi de données binaires. Chaque champs correspond à une propriété et chacune de ces propriétés peut adopter son propre format. (binaire, XML, JSON, texte)

Format des dates et heures

Les dates et heures ont leur propre standard : ISO-8601.

Utilisez le format court pour les dates et le format complet pour date et heure.

Les codes HTTP

200 : message de réponse bien interprétée

201 : une ressource a été crée

304 : rien n’a été modifié

400 : requête non comprise

401 : accès non autorisé à l’utilisateur

403 : accès purement et simplement interdit

404 : élément non trouvé

500 : erreur du serveur

DNS

Utilisez, dans la mesure du mesure, un nom de domaine spécifique pour vos API.

ex. http://api.monservice.com

Version

Utilisez un chemin spécifique pour chaque version de votre API.

ex. http://api.monservice.com/v1/

Faire référence à une autre ressource

Utilisez les suffixes « _url » ou « _href » qui sont particulièrement adaptées. Surtout si vous faites références à des objets binaires.

Pour une autre entité, vous pouvez utiliser « _id » ou « _identifier ».

Identifier une ressource

On identifie une ressource soit par « id », soit par « identifier ». Parfois aussi par « url » ou « href ».

Représentation binaire

Certains objets ont des propriétés binaires.

Selon le volume d’information, utilisez :

- soit « url » / « href » ou « maprioriete_url »  pour faire référence à une URL de téléchargement

- soit « data » ou « mapropriete_data » afin de proposer une représentation encodée en Base64 des données.

Envoyer / récupérer des données binaires

Pour envoyer par exemple une photo avec un commentaire, utilisez le multipart/form-data.

POST /photos

champs « comment » : contenu texte

champs « photo » : la photo, en binaire

champs « thumb » : la miniature de la photo, en binaire

En réponse, ou à la lecture :

GET /photos/12

{   "id": 12,   "comment": "mon texte",   "photo_url": "http://lien_vers_photo.jpg",   "thumb_url": "http://lien_vers_thumb.jpg" }

C’est finalement très simple. :-)

Vous pouvez également choisir d’avoir des objets spécifiques pour les fichiers à télécharger, ce qui peut être pratique pour avoir par exemple les dates de modification.

{   "id": 12,   "comment": "mon texte",   "photo": {     "url": "http://lien_vers_photo.jpg",     "updated_at": "2013-04-22T06:00:00Z"   },   "thumb": {     "url": "http://lien_vers_thumb.jpg",     "updated_at": "2013-04-22T07:00:00Z"   }, }

 Gestion des erreurs

Ne pas avoir de code erreur autres que 200 ou 500 peut parfois s’avérer utile.

Pour cela, utilisez le paramètre « suppress_error_codes » dans votre URL.

Egalement, pensez à renvoyer un message d’erreur explicite.

{   "errors": [     {       "message": "Password length is at least 8 characters.",       "code": 400     },     {       "message": "Email format is invalid.",       "code": 400     }   ] }

Gestion du cache

L’utilisation des en-têtes Etag/If-not-match permet une gestion plus efficace du cache.

Egalement, les en-têtes Last-Modified/If-modified-since sont très efficaces côté performances.

Authentification

Si vous souhaitez authentifier votre client et/ou votre utilisateur, je ne peux que vous recommander le protocole OAuth 2.0.

Il est simple, fiable et performant. Particulièrement adapté aux services web moderne.

L’authentification basique sur du HTTPS est également fiable et a l’avantage d’être la plus simple de toutes.

Limites

Les limites d’accès aux ressources peuvent être définies via les en-têtes HTTP X-RateLimit-Limit et X-RateLimit-Remaining. X-RateLimit-Reset permet de définir à quelle date/heure la limite va être réinitialisée.

Outils de développement

Les outils de développement les plus adaptés sont les suivants.

Si vous ne connaissez que le PHP, utilisez le framework Symfony 2 (Dailymotion) qui est bien conçu pour les services web.

Si vous êtes plus à l’aise avec Java/Scala, le framework Play est assez sympa, bien qu’un peu jeune.

Si vous êtes à l’aise avec Ruby, je ne peux que vous conseiller le framework Ruby on Rails (Twitter, Shopify, Groupon, GitHub, Linkedin) et/ou son petit cousin Sinatra (idéal pour le prototypage rapide).

Si vous êtes aventurier et que vous visez plus de performances, Node.js (Linkedin, eBay) peut être utilisé seul ou en parallèle de l’un des frameworks pré-cités.

Share
Développement Web

Utiliser la Google Search Ajax API

Je profite de ce nouvel article sur le blog  de Kaeli Soft pour me présenter. Jérémie Veillet, jeune auto-entrepreneur de 26 ans, j’ai pour travail tout ce qui concerne la partie Recherche & Développement au sein de l’équipe. Je travail actuellement sur le site internet de la société, et sur différents moyens d’utiliser le qrcode au sein d’applications, mais sur cela nous reviendrons plus tard.

Je vais vous décrire en quelques étapes simples comment mettre en place sur votre site internet un champs de recherche Google personnalisé.

Prérequis : Avoir des connaissances de base en Javascript.

Tout d’abord il convient de créer une page HTML basique qui va nous servir de squelette pour afficher nos différentes recherches, appelons-la « recherche.html ». Elle contient pour le moment uniquement deux éléments div qui vont nous servir pour la suite.

<!doctype html> <html> <head> 	<meta http-equiv="content-type" content="text/html; charset=utf-8"/> 	<title>Moteur de recherche Kaeli Soft</title> </head> <body> 	<!-- Conteneur des résultats --> 	<div id="searchResults">Chargement...</div>   	<!-- Conteneur des contrôles de navigation --> 	<div id="searchcontrol">Chargement...</div> </body> </html>

Ensuite, nous devons lier notre page aux API de Google à l’aide d’un script pour pouvoir utiliser les fonctions mises à disposition.

<script src="http://www.google.com/jsapi" type="text/javascript"></script>

C’est facultatif mais chaque développeur peut demander gratuitement une clé d’API aux services de Google, cela leur permet de tracer plus facilement s’il y a un problème dans le script exécuté.

Tentons d’afficher le champs de Recherche Google. Créons une fonction Onload() qui va contenir le code javascript nous permettant de faire nos traitements :

<!doctype html> <html> <head> 	<meta http-equiv="content-type" content="text/html; charset=utf-8"/> 	<title>Moteur de recherche Kaeli Soft</title>    	<script src="http://www.google.com/jsapi" type="text/javascript"></script>     <script language="Javascript" type="text/javascript">//<![CDATA[     // Chargement du champ de recherche google, les deux paramètres sont oligatoires     // 1: nom de l'API à charger; 2: numéro de version de l'API (1.0)     google.load('search', '1');       // Fonction de traitement de la recherche     function OnLoad() {         // Créer un objet SearchControl qui permet de créer les contrôles basiques de la recherche       var searchControl = new google.search.SearchControl();       // WebSearch permet de limiter la recherche au Web (ou blogs, images, maps)       searchControl.addSearcher(new google.search.WebSearch());       // Affichage des champ de recherche       searchControl.draw(document.getElementById("searchcontrol"));          // Execute une recherche initiale        searchControl.execute("Google");     }     // Appeler cette fonction pour que le traitement s'effectue une fois le document chargé     google.setOnLoadCallback(OnLoad);     //]]>     </script> </head> <body> 	<!-- Conteneur des résultats --> 	<div id="searchResults">Chargement...</div>   	<!-- Conteneur des contrôles de navigation --> 	<div id="searchcontrol">Chargement...</div> </body> </html>

A cette étape vous devriez obtenir un champs de recherche et un résultat pour la recherche « google ». Bien sûr on peut initialiser la recherche pour qu’aucun résultat par défaut n’apparaisse, il suffit de mettre la méthode « execute » à vide.

Voyons maintenant, comment limiter la recherche à votre propre site et afficher plus de résultats sur la page. La méthode .setExpandMode permet de définir que l’on souhaite afficher l’intégrité des résultats (avec la constante EXPAND_MODE_OPEN), et la méthode .setRoot permet de forcer l’attachement des contôles de navigation sur le div souhaité (ici « searchcontrol »).

<!doctype html> <html> <head>    <meta http-equiv="content-type" content="text/html; charset=utf-8"/>    <title>Moteur de recherche Kaeli Soft</title>    <script src="http://www.google.com/jsapi?key=ABQIAAAA0hDneawcf7yozxJWOReHhxQPxJxl0OR9X1wz4qymITTzqEUA-RQWsCurC_KFwiw1_cM9Sw7_aU4peA" type="text/javascript"></script>    <script language="Javascript" type="text/javascript">//<![CDATA[     // Chargement du champ de recherche google, les deux paramètres sont oligatoires     // 1: nom de l'API à charger; 2: numéro de version de l'API (1.0)     google.load('search', '1');       // Fonction de traitement de la recherche     function OnLoad() {         // Créer un objet SearchControl qui permet de créer les contrôles basiques de la recherche       var searchControl = new google.search.SearchControl();         // Définition des options du champ de résultats       var options = new google.search.SearcherOptions();       // Option permettant d'afficher tout les résultat trouvés, et des pages supplémentaires si les résultats sont nombreux       options.setExpandMode(google.search.SearchControl.EXPAND_MODE_OPEN);      // Attachement des contrôles à l'élément racine de la page qui possèdent l'id="searchcontrol"      options.setRoot(document.getElementById("searchcontrol"));       // Ajout d'un objet WebSearch pour préciser que l'on limite à la recherche web     // BlogSearch pour la recherche sur les blogs     // LocalSearch pour une recherche dans une localité     // ImageSearch pour rechercher des images      var siteSearch = new google.search.WebSearch();     // Restrictions de recherche     // setUserDefinedLabel: définit un label pour les résultats de recherche      siteSearch.setUserDefinedLabel("kaelisoft.fr");     // setUserDefinedClassSuffix: définit le suffixe des classes CSS des résultats (ex:gsc-resultsRoot-siteSearch)      siteSearch.setUserDefinedClassSuffix("siteSearch");     // setSiteRestriction: domaine du site sur lequel on veut chercher      siteSearch.setSiteRestriction("kaelisoft.fr");     // On applique les options de restrictions à la recherche      searchControl.addSearcher(siteSearch, options);       // Les résultats de recherche sont écrit dans l'élément qui possèdent l'id="searchResults"      searchControl.draw(document.getElementById("searchResults"));       // Execute une recherche initiale      searchControl.execute("Google");     }     // Appeler cette fonction pour que le traitement s'effectue une fois le document chargé     google.setOnLoadCallback(OnLoad);     //]]>     </script> </head> <body>    <!-- Conteneur des résultats -->    <div id="searchResults">Chargement...</div>       <!-- Conteneur des contrôles de navigation -->     <div id="searchcontrol">Chargement...</div> </body> </html>

Alors maintenant que l’on à fait ça, vous me direz, ce n’est pas forcément ce qu’il y à de plus beau, ou très adapté au design de votre site. Heureusement, Google à tout prévu, et il est possible d’entièrement customiser l’affichage, du champs de recherche aux résultats, par l’intermédiaire de feuille de style CSS.

Imaginons que l’on ne veuille afficher que le champ texte pour la recherche, pas de boutons « Recherche », ni de bouton pour effacer et surtout pas de logo « Fournis pas Google ». Pour connaitre facilement le nom des class à modifier, je conseille d’utiliser l’inspecteur d’éléments (Safari) ou d’utiliser le plugin Firebug pour Firefox (disponible ici).

Il faut alors ajouter dans l’entête du fichier html un petit peut de CSS:

<style type="text/css">    .gsc-branding,     .gsc-title,     .gsc-stats,     .gsc-search-button,     .gsc-clear-button {        visibility: hidden;    } </style>

Maintenant essayons de booster un peu ces champ de recherche en rendant le bouton rechercher noir et le champ de saisie avec des bords ronds.

.gsc-search-button{    background-color: #000000;    color: #ffffff;    border: 1px solid #000000;    /* Border-radius  */    -moz-border-radius: 32px;    -webkit-border-radius: 32px;    border-radius: 32px; }   input[type=text] {    width: 140px;    font-size: 13px;    text-align: left;    color: #000000;    background-color: #ffffff;    border: 1px solid #000000;      /* Border-radius  */    -moz-border-radius: 32px;    -webkit-border-radius: 32px;    border-radius: 32px; }

vous pouvez télécharger le fichier complet ici : recherche.html

Ceci n’est qu’une méthode pour interagir avec les outils de rechercher Google, ici avec javascript, mais on peut aller encore plus avec PHP, Java, Python, mais ceci sera peut être l’objet d’un autre article.

Share