SOAP dans les navigateurs Gecko
Un article de MDC.
Cet article décrit comment accéder à un service Web en utilisant SOAP et des fonctions JavaScript disponibles dans les navigateurs Gecko récents.
Sommaire |
[modifier] Introduction
Simple Object Access Protocol (SOAP) est la base de conception des services Web. C'est un protocole XML utilisé pour pour communiquer et interopérer avec les services Web. Avec Mozilla 1.0 (sur lequel est basé Netscape 7.0x) et Firefox, il est maintenant possible pour le navigateur de communiquer directement avec les services Web en utilisant son implémentation SOAP de bas niveau à l'aide de JavaScript.
L'interface JavaScript de Gecko pour l'établissement des appels SOAP est une API de bas niveau qui requiert la construction de l'enveloppe SOAP en utilisant plusieurs objets JavaScript spécifiques à SOAP. Ce document couvre les opérations SOAP de base. Pour des informations plus détaillées sur l'API de bas niveau de SOAP dans Gecko, voir SOAP Scripts in Mozilla.
L'utilisation de JavaScript pour les communications avec les services Web est sujette aux mêmes politiques de sécurité que tous les autres scripts en terme d'accès inter-domaines. Par conséquent accéder à des services Web situés sur des serveurs autres que celui où est exécuté le JavaScript constitue une violation de la politique inter-domaines. Ce document montrera comment détourner temporairement ces règles pour la conduite de tests.
[modifier] Paramétrer un appel SOAP
L'objet le plus basique est SOAPCall, il est utilisé pour initier et invoquer un appel SOAP.
var mySOAPCall = new SOAPCall();
mySOAPCall.transportURI = "http-based service URI"
var parameters = new Array();
mySOAPCall.encode(SOAPCall.VERSION_1_1,
// method
"method", "namespaceURI",
// header block
0, null,
// parameter
parameters.length, parameters);
var response = mySOAPCall.invoke();
Un objet SOAPCall à un membre appelé transportURI, qui est l'URI de l'emplacement où il doit envoyer l'appel SOAP. La méthode encode() requiert le nom de la méthode à appeler depuis le service Web, son namespaceURI, le nombre de SOAPParameters passé, et un tableau de SOAPParameters qui contient tous les paramètres. Tous ces paramètres peuvent sont regroupés dans le fichier WSDL du service Web, qui sera abordé dans les exemples suivants.
Les paramètres SOAP sont créés à l'aide de l'objet SOAPParameter. Ce sont des paires nom/valeur qui sont passées au service Web.
var param = new SOAPParameter(); param.name = "translationmode"; param.value = "en_fr";
[modifier] Traitement d'une réponse
Une fois que invoke() a été appelé, Gecko génère l'enveloppe SOAP et l'envoie à l'URI spécifiée. Comme la requête est synchrone, la réponse sera la valeur retournée par invoke().
var returnObject = mySOAPCall.invoke();
if(returnObject.fault){
alert("An error occured: " + returnObject.fault.faultString);
} else {
var response = new Array();
response = returnObject.getParameters(false, {});
alert("Return value: " + response[0].value);
}
La valeur retournée par invoke() est stockée et examinée pour un membre fault. Si il existe, une erreur se produit du côté du service Web, et le message d'erreur est stocké dans fault.faultString. Si fault n'existe pas, nous appelons la fonction getParameters() sur l'objet retourné pour récupérer les SOAPParameters retournés.
[modifier] Exemple
L'exemple utilise un service Web existant, Babelfish, fournit par xmethods.net. Le service Web Babelfish permet des traductions dans de nombreuses langues. Il prend deux paramètres en entrée : une chaîne au format « originalLanguage_resultLanguage » et le texte à traduire. Le fichier WSDL du service Web Babelfish est disponible à cette adresse et contient toutes les informations nécessaires au paramétrage d'un appel SOAP de bas niveau vers le service Web.
La première étape est de déterminer l'emplacement du service Web, qui sera la valeur du membre transportURI de SOAPCall. Elle peut être trouvée dans l'élément service de WSDL, et plus spécifiquement dans l'attribut location de soap:address.
WSDL:
<service name="BabelFishService">
<documentation>
Traduit des textes dans de nombreuses langues.
</documentation>
<port name="BabelFishPort" binding="tns:BabelFishBinding">
<soap:address location="http://services.xmethods.net:80/perl/soaplite.cgi"/>
</port>
<service>
JavaScript:
var babelFishCall = new SOAPCall();
babelFishCall.transportURI = "http://services.xmethods.net:80/perl/soaplite.cgi";
...
L'étape suivante est plus complexe : déterminer exactement quels paramètres le service Web attend qu'on lui envoie. Le service Web Babelfish ne possède qu'une méthode, « BabelFish », qui est représentée dans le WSDL entre la balise operation, qui est un enfant de l'élément portType. Chaque operation WSDL possède deux enfants : les éléments d'entrée et de sortie, qui peuvent contenir les types attendus. Les types sont définis dans les éléments message, au nombre de deux : BabelFishRequest, qui est ce qu'on passe au service Web, et BabelFishResponse, le type de retour.
BabelFish attend l'opération deux dans les paramètres translationmode et sourcedata. L'exemple de la figure 5 va traduire la chaîne « I am » d'anglais en français.
WSDL: <message name="BabelFishRequest"> <part name="translationmode" type="xsd:string"/> <part name="sourcedata" type="xsd:string"/> </message> <message name="BabelFishResponse"> <part name="return" type="xsd:string"/> </message> <portType name="BabelFishPortType"> <operation name="BabelFish"> <input message="tns:BabelFishRequest"/> <output message="tns:BabelFishResponse"/> </operation> </portType> JavaScript: // SOAP parameters var param1 = new SOAPParameter(); param1.value = "en_fr"; param1.name = "translationmode"; var param2 = new SOAPParameter(); param2.value = "I am"; param2.name = "sourcedate"; // combine the 2 params into an array var myParamArray = [param1,param2];
Ensuite, il faut définir et invoquer l'objet SOAPCall. « BabelFish » est la méthode que notre exemple veut utiliser pour le service Web. Le prochain paramètre est l'espace de nommage attendu qui doit être passé au service Web pour la méthode BabelFish.
Ceci peut être trouvé dans le l'élément WSDL binding. L'élément binding possède un enfant operation pour la méthode BabelFish. L'espace de nommage voulu est la valeur de l'attribut namespace de soap:body qui se trouve dans l'élément input.
WSDL:
<binding name="BabelFishBinding" type="tns:BabelFishPortType">
<soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>
<operation name="BabelFish">
<soap:operation soapAction="urn:xmethodsBabelFish#BabelFish"/>
<input>
<soap:body use="encoded" namespace="urn:xmethodsBabelFish"
encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
</input>
...
</operation>
</binding>
JavaScript:
babelFishCall.encode(0, "BabelFish", "urn:xmethodsBabelFish", 0, null, myParamArray.length, myParamArray);
var translation = babelFishCall.invoke();
Comme on l'a vu à la figure 5, la réponse de la méthode BabelFish ("BabelFishResponse") est un paramètre, à savoir une chaîne. Après avoir vérifier que fault n'a pas été retourné, la méthode getParameters() de l'objet retourné est utilisée pour récupérer un tableau de SOAPResponses. Comme on n'attend qu'un seul paramètre en retour -- le texte traduit -- la méthode alert() est utilisée pour afficher la traduction.
JavaScript:
if(translation.fault){
// erreur retournée par le service Web
alert(translation.fault.faultString);
} else {
// nous attendons un seul SOAPParameter en retour - la chaîne traduite.
var response = new Array();
response = translation.getParameters(false, {});
alert("Translation: " + response[0].value);
}
Comme indiqué dans l'introduction, les appels SOAP obéissent à une politique d'accès inter-domaines des scripts. Il existe deux façons de contourner cette politique de sécurité pour conduire des tests :
-
Exécutez le script depuis votre disque local.
Enregistrez localement le code sur votre disque dur.
Le modèle de sécurité inter-domaines ne concerne pas les codes exécutés depuis un disque local.
-
Activer l'accès inter-domaine
Vous pouvez contourner la vérification inter-domaine en définissant une préférence comme expliqué dans l'article contournement des restrictions de sécurité et signature de code (à traduire) et en ajoutant une commande JavaScript pour demander une dérogation à la vérification inter-domaine.
Après avoir contourner la vérification, démarrez le navigateur et chargez cette page exemple modifiée. Il vous sera demandé (dans une boîte de dialogue) l'autorisation de désactiver l'inter-domaine (pour cette session) de la fonction générant l'appel SOAP. Le seul changement est l'ajout de
netscape.security.PrivilegeManager.enablePrivilege("UniversalBrowserRead");à la fonction qui génère l'appel SOAP.
JavaScript:
var babelFishCall = new SOAPCall();
babelFishCall.transportURI = "http://services.xmethods.net:80/perl/soaplite.cgi";
// paramètres SOAP
var param1 = new SOAPParameter();
param1.value = "en_fr";
param1.name = "translationmode";
var param2 = new SOAPParameter();
param2.value = "I am";
param2.name = "sourcedate";
// combinaison des 2 paramètres dans un tableau
var myParamArray = [param1,param2];
babelFishCall.encode(0, "BabelFish", "urn:xmethodsBabelFish", 0, null, myParamArray.length, myParamArray);
var translation = babelFishCall.invoke();
if(translation.fault){
// erreur retournée par le service Web
alert(translation.fault.faultString);
} else {
// nous attendons un seul SOAPParameter en retour - la chaîne traduite.
var response = new Array();
response = translation.getParameters(false, {});
alert("Translation: " + response[0].value);
}
[modifier] Chemin de l'enveloppe Soap
Voici un HTTP dump (utilisant l'outil multiplate-forme Ethereal) de ce qui a été vraiment envoyé et reçu lorsque l'exemple a été exécuté :
Sent:
POST /perl/soaplite.cgi HTTP/1.1
Host: services.xmethods.net:80
...
Content-Type: text/xml
Content-Length: 516
<env:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:enc="http://schemas.xmlsoap.org/soap/encoding/"
env:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:xs="http://www.w3.org/1999/XMLSchema"
xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance">
<env:Header/>
<env:Body>
<a0:BabelFish xmlns:a0="urn:xmethodsBabelFish">
<a0:translationmode xsi:type="xs:string">en_fr</a0:translationmode>
<a0:sourcedata xsi:type="xs:string">I am</a0:sourcedata>
</a0:BabelFish>
</env:Body>
</env:Envelope>
Recieved:
HTTP/1.1 200 OK
Date: Tue, 11 Mar 2003 20:28:11 GMT
Server: Apache/1.3.26 (Unix) Enhydra-Director/3 PHP/4.0.6 DAV/1.0.3 AuthNuSphere/1.0.0
SOAPServer: SOAP::Lite/Perl/0.52
Content-Length: 532
...
Content-Type: text/xml; charset=utf-8
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/1999/XMLSchema">
<SOAP-ENV:Body>
<namesp1:BabelFishResponse xmlns:namesp1="urn:xmethodsBabelFish">
<return xsi:type="xsd:string">je suis</return>
</namesp1:BabelFishResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
[modifier] Ressources
SOAP Scripts in Mozilla (en) par Ray Whitmer
Using the Mozilla SOAP API (en) par Scott Andrew LePera et Apple Developer Connection.
The Latest w3.org SOAP Specification (en)
Calling SOAP Servers from JS in Mozilla (en), article de OnLamp.com par Zachary Kessin
SOAPCall documentation on XULPlanet.com (en)
SOAPResponse documentation on XULPlanet.com (en)
[modifier] Information sur le document original
- Auteur(s) : Doron Rosenberg
- Publication : 4 mars 2003
- Copyright : Copyright © 2001-2003 Netscape.
- Adresse d'origine : http://devedge-temp.mozilla.org/viewsource/2003/soap/01/index_en.html
- Note : cet article faisait partie du site DevEdge.