Mozilla Utilisation de l'API SOAP de Mozilla

REMARQUE ! Les informations sur cette page sont largement obsolètes. Pour obtenir des informations à jour sur le projet Mozilla, consulter la page de la communauté Mozilla francophone, leur blog principal et leur blog technique.

  • Document original : oreillynet.com
  • Date orignale : 30 août 2002
  • Auteur : Scott Andrew LePera
  • Publication : © Copyright 2002 Scott Andrew LePera
  • Traduction : Bruno Ethvignot
  • Mise à jour : 14/10/2005

Introduction

Bien qu'encore balbutiant, l'âge des services Web et de SOAP a déjà créé une demande très variée de technologies client. Une recherche de « client SOAP » donne d'innombrables implémentations pour C++, Perl, .NET, PHP et Java. Si vous creusez un peu plus profondément, vous pouvez même trouver des clients pour des langages comme Ruby, Python et Tcl. La plupart de ces clients opèrent au niveau serveur, comme middleware ou comme composant d'un système plus grand.

Cependant les clients Web sont traditionnellement mis à l'écart, jusqu'à présent la création de messages SOAP et la connexion aux services web convenaient mieux aux applications serveurs spécialement conçus pour ces tâches.

Jusque récemment, c'était vrai. Avec la sortie de Mozilla 1.0, le monde a maintenant un navigateur qui supporte nativement SOAP. Vous n'avez plus besoin de faire des assemblages, l'exécution et le traitement les opérations SOAP incombent seulement au côté serveur. Une application Web s'exécutant dans Mozilla (ou dans un client utilisant le même moteur de script, comme Netscape 7.0) peut maintenant faire des appels SOAP directement du client sans exiger que le navigateur n'ait besoin de faire un rafraîchissement ou des appels supplémentaires au serveur. Les données retournées d'une opération SOAP peuvent être accédées via les même méthodes DOM niveau 2 utilisées pour parcourir un document XML.

Note : les scénarios de script utilisés dans cet article ont été développés en utilisant Mozilla 1.0 sur un iBook sous Mac OS X. Seules les plus récentes version de Mozilla incluent l'API SOAP. Pour exécuter ces scripts, vous devrez copier le code dans un document HTML et l'exécuter de votre machine en local (voir les informations de sécurité, ci-dessous). NDT : Les exemples ne fonctionnent pas dans toutes les versions de Mozilla qui ont suivies la 1.0. En effet une régression identifiée sous le bogue 202725 générait des erreurs « permission denied » lors de l'appel de la méthode getElementsByTagName sur une réponse SOAP. Le bogue était présent dans Mozilla 1.4, mais est corrigé dans Mozilla 1.6a. Je n'ai pas testé les autres versions.

L'API SOAP de Mozilla

L'API SOAP de Mozilla est une interface JavaScript d'une série d'objets conçus pour créer, envoyer et recevoir des messages SOAP. Ces messages sont codés en XML, mais vous ne devez pas en savoir beaucoup sur la partie XML de SOAP pour utiliser l'API de Mozilla. La construction d'un message SOAP est aussi facile que de créer un autre objet JavaScript.

Un message SOAP de base contient quelques informations clef : l'URI du service cible, le nom de la méthode du service que vous voulez appeler et une série de paramètres à passer en arguments à la méthode. Une fois que ces éléments sont en place, l'appel SOAP est prêt à être exécuté.

J'ai choisi la populaire API Web de Google comme le service SOAP cible pour ces scripts d'exemples. Puisque Google impose des limites d'utilisation de leur API, vous devrez vous procurer une clef gratuite de l'API Google afin que ces scripts puissent accéder complètement aux données de la recherche.

L'invocation de services SOAP via l'API Mozilla peut être faite de façon synchrone ou asynchrone. Un appel SOAP synchrone obligera le script à attendre la réponse du service avant de continuer — un comportement connu comme bloquant. Un appel asynchrone (non bloquant) permettra au au script de continuer sans attendre une réponse, et utilise un « écouteur » ou « listener » (une procédure de rappel ou callback). pour manipuler la réponse du service quand elle arrive. Les scripts d'exemple de cet article utilisent des appels SOAP asynchrones.

Si vous voulez expérimenter différents services en plus de Google, vous pouvez trouver une abondante liste d'adresses de services SOAP sur XMethods.

Problèmes de sécurité

Parce que l'API SOAP permet au navigateur de faire des appels HTTP à des services que vous (l'utilisateur) ne contrôlez pas, la sécurité de votre système devient un problème. Un navigateur client sécurisé, ne permettra pas par exemple l'exécution de scripts entre les frames si elles contiennent des pages de deux domaines différents. De la même façon il ne permettra pas à un script de faire des appels comportant des risques à un service d'un domaine externe. Après tout, qui sait quel genre du code potentiellement malveillant ce prétendu « service » va retourner ?

Pour assurer la sécurité de votre système, un script utilisant l'API SOAP de Mozilla doit être un script signé ou s'exécuter sur la machine locale de l'utilisateur. (Pour en savoir plus sur les scripts signés de Mozilla voir scripts signés et privilèges : un exemple.) Même en prenant ces précautions, Mozilla exigera que l'utilisateur accorde les privilèges de sécurité appropriés avant d'exécuter le script.

Construction du message SOAP

Vous créez un message SOAP tout comme un objet tableau ou image en exécutant script. Un certain nombre d'objets relatifs à SOAP sont disponibles, mais pour le moment vous devrez seulement vous inquiéter de ces quatre :

Les objets SOAPCall et SOAPParameters sont les seuls que vous devrez créer avec JavaScript. SOAPResponse et SOAPFault sont automatiquement produit quand le service retourne une réponse.

Identification des méthodes du service

Ainsi quelles méthodes pouvez-vous appeler d'un service web donné ? D'habitude un service fournira un WSDL (encore un autre schéma XML), un fichier décrivant les méthodes disponibles et les paramètres exigés pour les appeler. Un client SOAP intelligent sera capable de faire l'analyse syntaxique de ce fichier et produira automatiquement les interfaces nécessaires pour communiquer avec le service.

Mozilla est intelligent, mais pas encore assez intelligent — son interface WSDL est en cours de developpement. Alors pour le moment nous sommes réduit à lire le fichier WSDL nous-mêmes pour apprendre ce qu'un service peut offrir. Un guide d'initiation sur WSDL pourrait facilement remplir un autre article, donc je vais sauter les détails sanglants et uniquement indiquer les parties appropriées comme nécessaire partout dans cet article. NDT : Depuis Mozilla 1.4, Gecko peut se connecter aux services web utilisant le mandatement WSDL. Un article de DevEdge explique comment faire.

Le fichier WSDL de l'API Web de Google identifie trois méthodes : doGoogleSearch, doGetCachedPage et doSpellingSuggestion. De ces trois, je vais me concentrer sur doGoogleSearch pour le code d'exemple, mais je laisserai aussi un peu de place pour les deux autres méthodes. Je commencerai en définissant une fonction pour créer et envoyer un message SOAP spécialement conçu pour Google :

function callGoogle(method,params,callback){

}

La fonction callGoogle exige trois arguments :

callGoogle utilisera les valeurs de ces trois arguments pour créer un objet SOAPCall représentant le message que je veux envoyer.

Autoriser les privilèges de sécurité

Avant que vous ne créiez un message SOAP, vous devez permettre à l'utilisateur d'accorder les permissions « UniversalBrowserRead » au script pour pouvoir faire un appel à un service distant. Pour le faire, vous avez besoin d'utiliser le Privilege Manager, intégré d'origine au produit Netscape et au code de Mozilla.

function callGoogle(method,params,callback){
  try {
    netscape.security.PrivilegeManager.enablePrivilege("UniversalBrowserRead");
  } catch (e) {
    alert(e);
    return false;
  }
}

Le code ci-dessus doit se trouver à l'intérieur de la fonction JavaScript ou du bloc de code responsable de lancer l'appel SOAP et doit être avant l'appel lui-même. Quand ce code s'exécute, un message est présenté aux utilisateurs leur demandant d'accorder ou de refuser le privilège :

photo écran : La boîte de dialogue des priviléges dans Mozilla

Cela arrivera chaque fois que la fonction de callGoogle est invoquée.

Rappelez-vous que l'on peut seulement accorder ce privilège à un script signé ou s'exécutant sur la machine locale. Autrement, le code générera l'erreur « enablePrivilege not granted » l'appel de SOAP ne sera pas exécuté.

Création de SOAPCall

Une fois que l'on a donné au script la permission de s'exécuter, le travail suivant est de créer un objet SOAPCall :

function callGoogle(method,params,callback){
  try {
    netscape.security.PrivilegeManager.enablePrivilege("UniversalBrowserRead");
  } catch (e) {
      alert(e);
    return false;
  }
  var soapCall = new SOAPCall();
  soapCall.transportURI = "http://api.google.com/search/beta2";
}

La propriété transportURI de l'objet SOAPCall est une chaîne indiquant l'URI du point final du service. Vous pouvez le trouver vers la fin du fichier WSDL de Google, dans l'élément <service/>. NDT : Le fichier WSDL de Google se nomme GoogleSearch.wsdl et peut être téléchargé dans l'archive suivante proposée par Google.

Ensuite, le message doit être codé avec la méthode requise en lui fournissant les paramètres. Cela est fait en passant les arguments suivants à la méthode de codage de l'objet SOAPCall :

soapCall.encode(0, method, "urn:GoogleSearch", 0, null, params.length, params);

Le code ci-dessus n'est pas évident à décrire parce que certains des arguments ne sont pas nécessaires pour les opérations SOAP de base et ont donc des valeurs zéro et nulles. Les seuls arguments pour lesquels vous êtes concernés sont method, qui est la méthode du service à être invoqué et l'espace de nom du service cible du service (dans notre cas, l'espace de noms "urn: GoogleSearch", peut être trouvé dans le fichier WSDL en tant que valeur de l'attribut de targetNamespace , de l'élément <definitions/>).

Les deux derniers arguments donnés à la méthode de codage sont respectivement le nombre de paramètres passé à la méthode du service et le tableau des paramètres.

Invocation de l'appel

Maintenant vous êtes prêts à invoquer SOAPCall et envoyer la requête au service Google. La méthode asyncInvoke de l'objet SOAPCall prend un argument : un pointeur sur une fonction de rappel (callback) qui traitera la réponse SOAP.

Comme noté ci-dessus, la fonction de callGoogle exige une fonction de rappel comme troisième argument, mais je ne suis pas prêt à utiliser tel quel. Au lieu de cela, je vais faire une petite vérification d'erreur avant de remettre la réponse à la suite de l'application. Donc je le passerai à handleSOAPResponse  :

function callGoogle(method,params,callback)
{
  try {
    netscape.security.PrivilegeManager.enablePrivilege("UniversalBrowserRead");
  } catch (e) {
      alert(e);
    return false;
  }
  var soapCall = new SOAPCall();
  soapCall.transportURI = "http://api.google.com/search/beta2";
  soapCall.encode(0, method, "urn:GoogleSearch", 0, null, params.length, params);
  soapCall.asyncInvoke(
    function (response, soapcall, error)
     {
        var r = handleSOAPResponse(response,soapcall,error);
        callback(r);
      }
  );
}

La dernière partie de cet exemple exige un peu plus d'explication. Quand la fonction de rappel passée est exécutée par asyncInvoke, on lui donne trois arguments qui proviennent du résultat retourné par l'appel SOAP  :

Puisque vous voulez que la réponse aille à handleSOAPResponse pour la vérification d'erreur et ensuite à la fonction de rappel initialement donnée à callGoogle, vous devez envelopper les deux descripteurs dans une fonction anonyme passée à la méthode asyncInvoke. Rappelez-vous qu'asyncInvoke n'attend pas une réponse du service avant de permettre au script de continuer. Cette manière de faire assure que le script n'oublie pas la fonction de rappel initiale lorsque la fonction callGoogle se termine.

Bien, vous avez terminé la fonction callGoogle qui assemble et envoie les messages SOAP à Google. Maintenant il est temps d'utiliser handleSOAPResponse pour s'occuper de la réponse.

Traitement de la réponse SOAP

La fonction handleSOAPResponse reçoit les résultats de l'appel de SOAP et les vérifie pour s'assurer qu'il n'y a pas d'erreur SOAP (NDT : Les éléments Fault des enveloppes SOAP) ou d'erreur du service. Si aucune erreur SOAP ou erreur de service n'est trouvée, le script suppose que la réponse est valide et passe le SOAPResponse à la fonction de rappel initialement donnée par l'utilisateur à callGoogle.

Vérification des erreurs

La première étape est de voir si l'argument erreur contient une valeur autre que zéro. S'il c'est le cas nous pouvons supposer qu'une erreur fatale est arrivée et quitter le script :

function handleSOAPResponse (response,call,error)
{
    if (error != 0)
    { 
        alert("Service failure");
        return false;
    } 
}

Si aucune erreur n'est trouvée ici, le script continue à vérifier qu'il n'existe pas d'erreur SOAP.

Traitement d'un SOAPFault

Une erreur SOAP se produit habituellement lorsque quelque chose s'est vraiment mal passé pendant l'appel : un paramètre manquant, une méthode invalide, etc. Quand une telle erreur se produit, un objet SOAPFault est généré qui contient l'information sur ce qui a mal tourné pendant l'opération SOAP.

Pour tester SOAPFault, le script doit vérifier la propriété fault de l'objet SOAPResponse. Si aucune erreur ne s'est produite, la valeur de cette propriété sera nulle. Autrement, c'est un objet SOAPFault.

Un objet SOAPFault a les propriétés suivantes :

La fonction handleSOAPResponse ci-dessous utilise faultCode et faultString pour avertir l'utilisateur qu'une erreur s'est produite. Si vous désirez, vous pouvez changer les messages d'avertissement ou ajouter du code pour fournir un comportement supplémentaire dans le cas d'une erreur.

function handleSOAPResponse (response,call,error)
{
    if (error != 0)
    { 
        alert("Service failure");
        return false;
    } else 
    {
        var fault = response.fault; 
        if (fault != null) { 
            var code = fault.faultCode; 
            var msg = fault.faultString; 
            alert("SOAP Fault:\n\n" +
                "Code: "  + code +
                "\n\nMessage: " + msg
            );
            return false;
        } else 
        {
            return response;
        }
    }
}

Notez que dans le cas d'une erreur SOAP ou d'une erreur de service, une valeur false est retournée à la fonction de rappel spécifié dans callGoogle. Si la réponse passe ces vérifications, le script retourne le SOAPResponse complet à la fonction de rappel.

Utilisation de la fonction callGoogle

Je vais faire marche arrière pendant un instant et regarder comment utiliser la fonction callGoogle pour faire un appel SOAP.

D'abord, vous devez préparer un tableau de paramètres exigés par la méthode du service. Comme mentionné plus haut, l'API Web de Google fournit trois méthodes. Une d'entre elle, doSpellingSuggestion, exige deux paramètres : le mot ou l'expression que vous voulez vérifier et une clef d'API Google.

Le deuxième argument exigé par callGoogle est un tableau contenant les paramètres nécessaires pour faire l'appel. Ceci se fait facilement avec le constructeur SOAPParameter, qui exige deux arguments : dans l'ordre, la valeur et nom du paramètre à ajouter.

// crée le paramètre tableau
var params = new Array();

// remplacer 'yourKeyHere' par votre clé Google
params[0] = new SOAPParameter(yourKeyHere, "key");
params[1] = new SOAPParameter("brintey speers","phrase");

// maintenant on fait l'appel au service Google
callGoogle("doSpellingSuggestion",params,parseResult);

Voici un exemple plus complexe pour la méthode doGoogleSearch :

var p = new Array();
p[0] = new SOAPParameter(yourKeyHere, "key");
p[1] = new SOAPParameter("Mozilla", "q"); // la chaîne recherchée
p[2] = new SOAPParameter(0, "start");
p[3] = new SOAPParameter(10, "maxResults");
p[4] = new SOAPParameter(false, "filter");
p[5] = new SOAPParameter("", "restrict");
p[6] = new SOAPParameter(false, "safeSearch");
p[7] = new SOAPParameter("", "lr");
p[8] = new SOAPParameter("Latin-1", "ie");
p[9] = new SOAPParameter("Latin-1", "oe");
callGoogle("doGoogleSearch" ,p, parseResult);

Dans le code ci-dessus, parseResult est la fonction de rappel que nous voulons voir gérer le traitement d'une opération SOAP pleinement réussie (sans erreur SOAP, ni erreur de service). Puisque la fonction handleSOAPResponse s'occupe de la vérification d'erreur, vous ne devez pas vous en inquiéter dans votre fonction de rappel. Si une erreur de service ou une erreur SOAP sont trouvées, la valeur retournée à parseResult sera simplement false.

Analyse syntaxique de SOAPResponse

Le dernière partie de notre puzzle est réalité d'écrire la fonction de rappel parseResult pour traiter la réponse SOAP. Le premier travail est de voir si le résultat remis à parseResult après une opération SOAP est vraiment un objet SOAPResponse :

function parseResult(result)
{
    if (result == false)
    {
         return;
    }
}

Le script ci-dessus sort sans avertissement si aucun SOAPResponse n'est disponible. Une implémentation plus efficace fournirait une alerte ou un comportement supplémentaire.

Recherche des paramètres

Maintenant vous pouvez récupérer l'information retournée de la méthode du service SOAP. L'approche la plus directe est d'utiliser la méthode getParameters de l'objet SOAPResponse. Comme vous auriez pu le deviner, getParameters retourne un tableau contenant les paramètres retournés par le service SOAP.

function parseResult(result)
{
    if (result == false)
    {
         return;
    }
    var num = new Object();
    var params = result.getParameters(false,num);
}

L'appel à getParameters exige deux arguments : un booléen à false (indiquant que c'est un message de style RPC) et un objet JavaScript générique num, qui contiendra le nombre de paramètres à retourner.

Le nombre de paramètres retourné dépend du service et doit être décrit dans le fichier WSDL. Dans le cas de Google, les trois méthodes du service retournent un seul paramètre comme réponse. Dans le fichier WSDL de Google, conformément aux <message/>, vous pouvez voir que le paramètre est dans les trois cas un seul élément return.

Analyse syntaxique des valeurs de retour

La recherche des données du service est maintenant une simple question d'analyse syntaxique des paramètres. Chaque paramètre dans le tableau a les propriétés suivantes :

Mettons ces connaissances en pratique. Puisque le doSpellingSuggestion retourne uniquement un paramètre contenant l'orthographe suggérée, vous pouvez vous référer directement à la propriété value du paramètre pour récupérer la suggestion :

function parseResult(result)
{
    if (result==false)
    {
         return;
    }
    var num = new Object();
    var params = result.getParameters(false,num);
    var suggestion = params[0].value;
    alert("Suggested spelling: " + suggestion);
}

Alternativement, vous pouvez utiliser le DOM pour récupérer l'information via la propriété element du paramètre :

var suggestion = params[0].element.firstChild.nodeValue;

La possibilité d'utiliser le DOM est de cette façon est particulièrement utile quand les paramètres retournent un XML complexe plutôt qu'une simple paire noms/valeur. Un exemple est la méthode du service doGoogleSearch, qui fournit non seulement une information conséquente sur les résultats de la recherche, mais aussi des méta-informations concernant le temps de recherche, le nombre total de résultats et le filtrage. Par exemple, en recevant une réponse du service de recherche de Google, vous pouvez vouloir récupérer uniquement les noms et les tailles des fichiers en cache des documents correspondants. Avec le DOM, c'est assez simple :

function showResults(results)
{
    if (!results)
    {
        return;
    }
    var params = results.getParameters(false,{});
    var matches = params[0].element.getElementsByTagName("item");
    var str = "";
    for (var i=1;i < matches.length;i++)
    {
      var URL = matches[i].getElementsByTagName("URL").item(0).firstChild;
      var title = matches[i].getElementsByTagName("title").item(0).firstChild;
      var cache = matches[i].getElementsByTagName("cachedSize").item(0).firstChild;

      str += "<a href=\"" + URL.nodeValue + "\">" + title.nodeValue + 
          "</a> (" + cache.nodeValue + ")<br/>";
    }
    document.body.innerHTML = str;
}

Rentrez dans le jeu chez vous

Vous pouvez télécharger l'exemple complet que j'ai réalisé qui fonctionne, fait pour l'API de Google :

Recherche Google Mozilla

Cela couvre le processus entier, de la définition des paramètres à l'exécution de l'appel de SOAP à l'analyse syntaxique et l'affichage des résultats de recherche avec des méthodes du DOM. Allez-y expérimentez ce code et écrivez vos propres interfaces à d'autres services SOAP et créez en utilisant les données retournées dans vos applications Web.

En regardant au-delà du navigateur, le moteur de script fait partie du paquet Mozilla complet, donc il est possible d'écrire en XUL (Le langage d'interface utilisateur XML, avec lequel l'interface de Mozilla est construite) les applications qui profitent de la même API. L'API SOAP de Mozilla vous permet d'utiliser des standards web familiers — JavaScript et le DOM — pour intégrer facilement des services Web dans vos applications côté client.

D'autres lecture et ressources


Faire un commentaire.

(Site mise à jour le mardi 16 mars 2004)

Ce document à une CSS valide Ce document est conforme au XHTML 1.0