Tutorial - rebXR. (1/3) Tour d'horizon de XML-RPC


    Auteur      : Bruno Bord
    Date        : 7-Nov-2002
    Version     : 1.0
    Contact     : brunobord@yahoo.fr

Table des matières

1 Introduction et avertissement
2 XML-RPC, la théorie
2.1 La voix du maître :
2.2 Une métaphore parlante
2.3 Techniquement
2.4 XML-RPC par l'exemple
2.5 SOAP, histoire de se débarrasser
2.6 Alors ? Tu conclus quoi ?
3 rebXR, ça tue !
3.1 Téléchargement et installation
3.2 Comment on s'en sert ?
3.3 La curiosité est un joli défaut
3.4 Quelques exemples de webservices publics
4 Perspectives
5 Bibliographie et Références
5.1 Musique
5.2 Livres
5.3 URLs
6 Remerciements
[ retour ]

1 Introduction et avertissement

Je tiens à avertir le lecteur non averti que je vais te tutoyer. Merci de ne pas s'en formaliser, c'est juste une sale manie. Sur le web, tout le monde se tutoie. Alors, pourquoi pas dans une doc ? D'autant plus que quelqu'un qui s'intéresse à REBOL et à XML-RPC ne peut pas être foncièrement mauvais. Donc, on se dit "tu".

Cet article a donc pour but de démontrer les mécanismes principaux de XML-RPC et décrire grossièrement rebXR. Cette application est l'oeuvre d'*Andreas Bolka*. Son site contient une documentation (assez sommaire) sur cette implémentation :

Consulter la documentation.

Dans un second temps, je développerais un tutorial sur un cas concret : la gestion d'un forum via PHP/MySQL et accessible en XML-RPC.

Puis nous verrons également comment programmer une version cliente graphique en REBOL capable d'afficher les messages du forum et évidemment d'y participer.

[ retour ]

2 XML-RPC, la théorie

Si tu es pressé, tu peux passer cette section ou la parcourir dans les grandes largeurs. Parce que tu constateras que l'utilisation de rebXR ne nécessite pas de connaissances particulières sur la norme XML-RPC précisément ; disons que c'est pour ta "webculture", histoire de voir en gros de quoi on parle.

2.1 La voix du maître :

*Dave Winer* : "It's a spec and a set of implementations that allow software running on disparate operating systems, running in different environments to make procedure calls over the Internet. It's remote procedure calling using HTTP as the transport and XML as the encoding. It's designed to be as simple as possible, while allowing complex data structures to be transmitted, processed and returned."- http://www.xmlrpc.com

Trad : "C'est une spécification et un jeu d'implémentations qui permet l'exécution de programmes sur un ensemble de systèmes d'exploitation hétérogènes, et qui s'exécute dans des environnement différents permettant de d'effectuer des appels de procédure au travers de l'Internet. C'est de l'appel de procédure distant (RPC) utilisant HTTP comme couche de transport et XML pour l'encodage. Il est conçu pour être aussi simple que possible, tout en permettant la transmission, le traitement et le renvoi de structures de données complexes."

2.2 Une métaphore parlante

RPC signifie Remote Procedure Call. C'est une norme d'échange qui permet à des "mondes" du réseau de communiquer entre eux. C'est tout simplement un langage commun, une sorte d'esperanto, de lingua franca entre les différents OS et/ou modes de communication.

Métaphore
  • Un français ne parle pas l'allemand
  • Un allemand ne parle pas le français
  • Mais les deux ont appris l'esperanto.

Quel est leur moyen de communication privilégié pour échanger des informations, des messages, des remarques, des ordres ? Leur langue commune, bien sûr.

Cette métaphore est particulièrement adapté pour l'espéranto, puisque cette langue inventée se voulait la plus simple possible, avec un minimum de règles de grammaire, aucune exception, aucun verbe irrégulier...

2.3 Techniquement

XML-RPC est une norme issue des travaux de Dave Winer, qui a participé à la création du protocole SOAP (Simple Object Access Protocol), qui est un autre moyen d'accéder à des webservices en décrivant les échanges sous un format XML.

Les spécifications de XML-RPC

Elle utilise (c'est la norme qui utilise, 'faut suivre) un formalisme XML qui se veut être le plus simple possible, donc facile à générer / traiter / parser. Aujourd'hui tout le monde sait traiter des document XML...

Quel intérêt ? Il est multiple : utiliser un niveau d'abstraction supplémentaire peut paraître inutile, voire idiot, mais en fait, ce format de transition est tout ce qu'il y a d'efficace. Une fonctionnalité (serveur), un code. Si c'est le mode d'affichage qui change, alors c'est le code de l'application d'affichage qui doit changer.

Pour un service donné :

Lorsqu'on développe un site internet à destination des browsers web classiques (HTML), on conçoit dans un langage de script serveur une superbe application qui parcourt la base de données et renvoie les informations déjà mises en forme. Mais si on doit développer la même fonctionnalité pour un browser WAP, par exemple, il faut tout reprendre de zéro et adapter la fonctionnalité à sa méthode d'affichage.

En utilisant XML comme format transitionnel, les fonctionnalités restent intactes, toutes les informations brutes sont disponibles. Il suffit seulement d'utiliser un programme d'affichage spécifique à mon navigateur pour les voir apparaître dans la mise en forme voulue.

Le webservice, c'est le moyen de faire du "write once, display many". A rapprocher des idéaux du JAVA : "write once, run many".

2.4 XML-RPC par l'exemple

Un petit exemple ne peut pas faire de mal. Je vais utiliser la fonction de test, le "hello world" du XML-RPC : getStateName.

URI

http://betty.userland.com/RPC2:80

Fonction

examples.getStateName

Description

On fournit un entier compris entre 1 et 50 et la fonction renvoie le nom de l'Etat des Etats-Unis correspondant. Follement intéressant, n'est-ce pas ?

2.4.1 Une question

    <?xml version="1.0"?>
    <methodCall>
        <methodName>examples.getStateName</methodName>
        <params>
            <param>
                <value><i4>42</i4></value>
            </param>
        </params>
    </methodCall>

On demande donc le nom du 42° Etat des Etats-Unis. Pourquoi 42 ? Lis Douglas Adams.

Dans le détail :

2.4.2 La réponse.

    <?xml version="1.0"?>
    <methodResponse>
        <params>
            <param>
                <value><string>South Dakota</string></value>
            </param>
        </params>
    </methodResponse>

Je t'ai fait grâce des headers qui accompagnent les messages. On peut y lire la source, la provenance, quel agent XML-RPC a été employé, etc... Inutile pour la démonstration.

2.4.3 Les types de données XML-RPC

i4 ou int entier
boolean booléen, true ou false
string chaîne de caractère
double réel double
dateTime.iso8601 variable date + heure aux normes ISO8601
base64 type binaire codé sur 64 bits
array tableau
struct types structurés

2.5 SOAP, histoire de se débarrasser

SOAP est un protocole homologué par le W3C. Soyons honnêtes : il est hautement plus développé que XML-RPC. Il est extensible et génère des requêtes plus complètes et plus précises que XML-RPC. Mais également plus complexes. Alors que tu as bien vu, un flux XML-RPC est lisible par un oeil humain, un flux SOAP est beaucoup moins sympa...

2.5.1 Une question

    <?xml version="1.0"?>
    <soap:Envelope
    xmlns:soap="http://www.w3.org/2001/12/soap-envelope"
    soap:encodingStyle="http://www.w3.org/2001/12/soap-encoding">
        <soap:Body xmlns:m="http://www.stock.org/stock">
            <m:GetStockPrice>
                <m:StockName>IBM</m:StockName>
            </m:GetStockPrice>
        </soap:Body>
    </soap:Envelope> 

2.5.2 La réponse

    <?xml version="1.0"?>
    <soap:Envelope
    xmlns:soap="http://www.w3.org/2001/12/soap-envelope"
    soap:encodingStyle="http://www.w3.org/2001/12/soap-encoding">
      <soap:Body xmlns:m="http://www.stock.org/stock">
        <m:GetStockPriceResponse>
          <m:Price>34.5</m:Price>
        </m:GetStockPriceResponse>
      </soap:Body>
    </soap:Envelope> 

Perso, je trouve ça imbittable. Alors, c'est sûr, ça fait bien d'utiliser les espaces de noms, les machins XML-Schema et les réponses alambiquées. C'est connu, le W3C nous abreuve de spécifications et autres documents tous plus incompréhensibles les uns que les autres. Le résultat, c'est qu'il apparaît évident que les développeurs n'ont pas de temps à perdre à noyer le poisson, simplement par ce qu'il faut respecter les normes du W3C.

Ça me rappelle une expression que la décence et le bon goût m'interdit de citer ici, mais tu auras bien compris que ça parlait de mouches et de pratiques zoophiles relativement acrobatiques.

2.5.3 Calmons-nous

SOAP ne peut pas être concurrent de XML-RPC. Et réciproquement. Il y a du pour et du contre. SOAP est complet, normalisé, puissant, extensible. XML-RPC est léger, rapide et couvre la plupart des problèmes du type webservice.

Comme je le lisais récemment sur slashdot.org, les développeurs ont parfois trop souvent tendance à transformer leur langages de programmation en religion. C'est à partir de ce genre de débats qu'on en vient à des trolls sans fin : ASP ou PHP ? IIS ou APACHE ? JAVA ou REBOL ? On en viendrait presque aux mains. C'est presque des guerres de religion. Obscurantisme et tout le toutim.

Je ne tiens pas à allumer la mèche.

Si un jour un parseur SOAP en REBOL vient à naître, je le regarderais avec grand intérêt, ce protocole ayant tendance à se développer, et, sait-on jamais, à se généraliser pour normaliser les échanges client/webservice.

2.6 Alors ? Tu conclus quoi ?

La démonstration est flagrante... J'ai envoyé via le réseau (en http) une question à un serveur qui m'a répondu dans la même langue. XML-RPC.

On est au plus près de la philosophie REBOL : simplicité, élégance et portabilité.

La question se rédige en deux parties : le nom de la fonction et ses paramètres. Pour aiguiller un tout petit peu le serveur, je lui ai précisé les types des données employées.

La question et la réponse sont loin d'être encombrées d'informations superflues. On va à l'essentiel. Dans l'exemple précédent, on me renvoie une chaine ? Ben alors, seule cette chaîne est reçue. Dans le cadre d'une page web normale, j'aurais reçu des tonnes d'infos parfaitement inutile et pourtant rigoureusement indispensables pour mon browser.

    <html>
        <head>
            <title>La réponse à ma question getStateName</title>
        </head>
        <body>
            South Dakota
        </body>
    </html>

Parce que c'est assez clair : je ne me suis absolument pas soucié de la méthode d'implémentation de XML-RPC du côté du serveur.

Où étaient stockés les noms des Etats ? Dans une base de données relationnelle ? MySQL ou ACCESS ? dans des fichiers textes ?

Et quel était le langage de programmation sur le serveur ? PHP ? ASP ? REBOL ?

La seule contrainte pour utiliser le service est du côté de l'implémentation du client. Il lui faut savoir :

  1. Emettre une requête correctement formulée en XML-RPC
  2. Décoder la réponse du serveur

Pour ce faire, nous pourrions nous mettre à fabriquer un parseur XML utilisant les spécifications XML-RPC de Userland.com. Mais nous n'allons quand même pas réinventer la roue, pas vrai ? Alors, on va utiliser une classe REBOL.

[ retour ]

3 rebXR, ça tue !

3.1 Téléchargement et installation

rebXR est accessible à cette adresse :

Téléchargement

C'est une archive ZIP à décompresser dans un répertoire de son choix. Cette archive contient 5 fichiers REBOL :

Les deux premiers fichiers sont issus du travail de Gavin F. McKenzie. Cette classe permet de transformer un flux XML en objets structurés REBOL. C'est un parseur XML extrêmement efficace sur lequel rebXR s'appuie pour lire/écrire les messages XML-RPC

ce que je trouve dommage

Ces cinq fichiers déterminent l'ensemble des objets et fonctions à utiliser dans une transaction XML-RPC. Donc, les programmes voulant utiliser le module rebXR doivent systématiquement les intégrer tous les cinq au début du programme. Donc, ça commence comme ça :

    do %xml-object.r
    do %xml-parse.r
    do %xmlrpc-client.r
    do %xmlrpc-marshaler.r
    do %xml-writer.r

Bon, on peut tricher un peu, en fabriquant un fichier %include.r qui contiendra ces cinq lignes de programme, mais je trouve un peu dommage de devoir garder ces cinq fichiers dans un répertoire. A contrario, le module rugby de Maarten Koopmans se génère à partir de plusieurs fichiers pour en fabriquer un seul.

3.2 Comment on s'en sert ?

3.2.1 Le code

En admettant que toutes les bibliothèques nécessaires à l'utilisation de XML-RPC sont chargées (cf. la note ci-dessus), voici le code d'appel :

    >>;création de l'objet client
    >>remote: make xmlrpc-client []
    >>;définition de l'URI du service web
    >>remote/set-server http://betty.userland.com/RPC2:80
    >>;appel de procédure distante = RPC
    >>print remote/exec [examples.getStateName 42]
    == "South Dakota"

Encore une fois, REBOL + XML-RPC, ça ne peut que donner un code d'une simplicité déconcertante. Trois lignes de programme, et on accède à un webservice à distance, qui nous renvoie "South Dakota" quand on lui demande "42 ?".

Pour info

La commande set-server ne connecte pas au service web. On ne fait que définir l'adresse pointée par l'objet "remote". La connexion se fera seulement lors de l'appel à une fonction.

3.2.2 Une balise ? où ça une balise ?

Le module rebXR simplifie en effet considérablement l'utilisation de XML-RPC. Tu seras d'accord avec moi, aucune connaissance particulière du formalisme XML et encore moins de la norme XML-RPC n'était nécessaire pour écrire la requête. A aucun moment je n'ai écrit ou lu la moindre balise XML dans mon code (que ce soit la question ou la réponse).

Là, tu commences à me haïr parce que j'ai quand même expliqué sur dix pages écran ce qu'était XML-RPC, ses avantages, les divers atouts d'un webservice, pourquoi, comment, etc... Mais je t'ai pas pris en traître. Il fallait directement passer à cette section.

C'est encore plus flagrant avec une réponse sous forme de polynôme. Dans l'exemple qui suit, la fonction test.getNomPrenom renvoie le nom et le prénom de la personne dont l'identifiant et "nombre" dans mon carnet d'adresses.

    ; en admettant que la fonction existe sur le serveur pointé
    ; par l'objet remote
    >>remote/exec [test.getNomPrenom 74]
    == ["Patrick" "Dubois"]

Tu l'as reconnu ? C'est bien un bloc. Un bon vieux bloc REBOL. Et si tu es malin :

    >>data-tab: remote/exec [test.getNomPrenom 74]
    == ["Patrick" "Dubois"]
    >>data-tab/1
    == "Patrick"

Et encore, on est sur des exemples simplissimes. On peut récupérer des types structurés avec des noms clairs pour chacun des champs renvoyés :

    >>data-tab: remote/exec [test.getFicheEmploye 12]
    == make hash! ["prenom" "Patrick" "nom" "Dubois" "age" 32]

Là, j'admets que c'est un peu moins sympa. Il faut compter de deux en deux pour avoir dans les indexes impairs le nom du champ renvoyé (prenom, nom, age) et dans les indexes pairs les valeurs de ces champs (Patrick, Dubois, 32).

3.2.3 Les blocs de blocs

Bien entendu, l'utilisation des tableaux peut grandement faciliter la récupération de listes de données structurées. Tiens, un avant-goût de la deuxième partie de l'article :

    >>data-tab: remote/exec [forum.getListeMessages 5]
    == [[2 "Titre plus"] [1 "Bienvenue"]]

Chaque message est dans un bloc, qui eux-même se trouvent dans un bloc (qu'on peut parcourir de manière classique en REBOL).

Les types

Tu auras bien sûr remarqué que les types sont respectés : une chaîne reste une chaîne, un entier reste un entier. Les types XML-RPC sont intégralement transformés en types de données REBOL.

Selon le degré de complexité (ou de simplicité) qu'on veut apporter au programme, on peut aussi renvoyer des blocs de structs.

    >>data-tab: remote/exec [forum.getListeMessages 5]
    == [make hash! ["id" 2 "titre" "Titre plus"] make hash! ["id" 1 "titre"
        "Bienvenue"]]

Les deux premiers messages du forum sont envoyés sous formes de blocs de blocs. Le premier message est dans data-tab/1. Son titre est dans data-tab/1/4.

Cette méthode peut paraître un peu alambiquée pour des enregistrement aussi simples, mais elle peut être utile. Imaginons un carnet d'adresses dans lequel certaines informations ne sont pas totalement disponibles (ex : le téléphone domicile qui doit rester secret, ou alors que certaines informations manquent à l'appel dans la base de données). On pourrait implémenter un webservice de telle façon qu'il n'enverrait que les informations disponibles à l'utilisateur. Et pour les identifier, il faudrait utiliser un type structuré "à géométrie variable".

    >>data-tab: remote/exec [test.getListeFichePublique]
    == [make hash! ["nom" "Patrick" "prenom" "Dubois" "age" 32] make hash! [
    "nom" "Corbeau" "téléphone" "01 42 32 44 77 888"]]

J'ai donc respecté mes spécifications tout en optimisant le flux de données transporté dans le message XML-RPC.

C'est aussi ça, l'élégance...

3.3 La curiosité est un joli défaut

Si tu es curieux, je te propose d'employer ton objet xmlrpc-client en mode debug.

    >>remote/set-debug true
    >>remote/exec [examples.getStateName 42]
    >>;surprise................

Tu verras ainsi passer l'ensemble des flux XML et de comprendre comment sont transformés ces flux d'un formalisme à un autre. Ca peut être également utile pour "décoder" les résultats renvoyés par un webservice pour lequel tu n'aurais pas de documentation particulière.

On peut aussi apprendre sous quelle plate-forme et dans quel langage a été implémentée le module XML-RPC du serveur. Absolument inutile, mais que veux-tu, si on est curieux, au moins, on sait.

3.4 Quelques exemples de webservices publics

3.4.1 Cover project

URL

http://covers.wiw.org/

URI

http://covers.wiw.org:80/RPC.php

Description

Ce projet référence les reprises de chansons d'un artiste à l'autre. On consulte ainsi une sorte de moteur de recherche en XML-RPC qui permet de retrouver l'artiste ayant repris "Highway to Hell" de AC/DC, ou quelles sont les chansons reprises par le groupe Pearl Jam, etc...

3.4.2 Google

URL

http://google.xmlrpc.com/

URI

http://google.xmlrpc.com:80/RPC2

Description

On peut interroger Google en XML-RPC !!! Il suffit de s'inscrire en ligne de manière gratuite. On obtient un mot de passe à transférer durant chaque interrogation, et on obtient les mêmes résultats que dans la page html interrogeable sur google. Mais ils sont structurés en XML-RPC, et donc parsable. Tout ce qu'il faut pour créer un client de moteur de recherche en REBOL, non ?

3.4.3 Current Time

URL

http://www.xmlrpc.com/currentTime

URI

http://time.xmlrpc.com:80/RPC2

Description

Renvoie la date et l'heure en Temps Universel (TU) au format RFC 868. Passionnant, mais à quoi ça peut servir ? Par exemple, on pourrait déterminer que des applications clientes auraient besoin d'une synchronisation à la minute (la seconde ?). Avant toute opération, elles récupèrent l'heure en TU, ce qui leur permet de déclencher les tâches très précisément. Moi qui suis passionné d'astronomie, je confirme que la récupération de ce genre d'infos est capitale pour les calculs astronomiques.

[ retour ]

4 Perspectives

Ecrire un client XML-RPC en REBOL consiste donc simplement à importer les fonctions de rebXR et des les exécuter sur un poste connecté au réseau. Le programme se chargera de la connexion au webservice, de l'envoi de la question et de la traduction REBOLienne de la réponse.

Le développement d'une interface cliente permettant d'exploiter les résultats consiste alors à savoir utiliser les blocs REBOL réceptionnés pour afficher ou traiter ces informations. On ne se concentre donc que sur l'essentiel : l'applicatif.

Il est a priori possible de fabriquer un serveur XML-RPC en REBOL. Après avoir questionné Andreas Bolka sur cette éventualité, il m'a détrompé : il n'y a pas pour l'instant de serveur standalone XML-RPC en REBOL. Il n'est disponible qu'en mode CGI.

Lors de la suite de cet article, nous utiliserons donc une classe PHP implémentant XML-RPC qui jouera le rôle du webservice. La base de données sera une base MySQL.

Nous devrons donc d'abord décrire les spécifications techniques du webservice, puis nous essaierons de fabriquer ce webservice. Enfin, nous réaliserons une application REBOL capable d'exploiter ces procédures mises à notre disposition pour interagir avec la base de données.

[ retour ]

5 Bibliographie et Références

5.1 Musique

Highway to Hell

AC/DC.

Les 9 Symphonies

Ludwig von Bethoveen, dirigées par Herbert Von Karajan. Pour l'inspiration.

Superunknown

Soundgarden.

5.2 Livres

Rebol Programmation

Olivier Auverlot, Editions Eyrolles.

Le guide galactique

Douglas Adams, Editions Denoël.

5.3 URLs

Spécifications XML-RPC

Le package rebXR.

RebolFrance.net.

Portail francophone sur REBOL. rhâ la vache ! y' même une chanson.

Editplus.

L'éditeur de texte sur lequel a été tapé cette documentation.

[ retour ]

6 Remerciements

Un profond remerciement est adressé à Andreas Bolka pour avoir conçu et réalisé l'extension rebXR. Je tiens aussi à le remercier pour sa disponibilité.

Je remercie également Jason Cunliffe qui m'a un peu guidé dans mes recherches sur XML-RPC.

Je me remercie Robert. M. Münch, pour son soutien sur son superbe outil : make-doc-pro.

Je remercie encore Olivier Auverlot de m'avoir ouvert ses pages sur le site rebolfrance.net.

Un grand merci à Sébastien Rénie qui m'a fait découvrir le langage REBOL.

[ retour ]

Document formatter copyright Robert M. Münch. Tous Droits Réservés.
XHTML 1.0 Transitional formaté par Make-Doc-Pro Version : 1.0.5 le 14-Nov-2002 à 19:16:54

 

Bruno Bord

Retour