mozilla
Los resultados de tu búsqueda

    SOAP en los navegadores basados en Gecko

     

    Este artículo muestra cómo acceder a los servicios web utilizando las posibilidades de SOAP y JavaScript disponibles en los últimos navegadores basados en Gecko.

    Introducción

    SOAP (Simple Object Access Protocol, protocolo simple de acceso a objetos) es la base sobre la que se construyen los servicios web. Es un protocolo basado en XML utilizado para poder comunicarse e interoperar con los servicios web. Mozilla 1.0 (sobre el cual ha sido construido Netscape 7.0x) y Firefox son capaces de comunicarse directamente con los servicios web a través de su implementación de SOAP a bajo nivel a través de JavaScript.

    La interfaz de JavaScript de Gecko que establece llamadas SOAP es una API de bajo nivel que precisa de una para construir el mensaje SOAP utilizando varios objetos de JavaScript específicos para SOAP. Este artículo explicará las operaciones básicas de SOAP. Para más detalles véase la API de SOAP a bajo nivel en Gecko aquí.

    Traducido cross domain access como acceso multidominio ¿¿?? El uso de JavaScript para la comunicación con los servicios web está sujeto a las mismas políticas de seguridad que otros scripts en términos de acceso multidominio. Por tanto, el acceso a servicios web ubicados en servidores distintos al servidor en el que se está ejecutando JavaScript violará la política de multidominio. Este artículo mostrará cómo esquivar temporalmente esto para hacer pruebas.

    Configurar una llamada SOAP

    El objeto más básico es SOAPCall, el cual es usado para iniciar e invocar una llamada SOAP.

    Figura 1 : Configuración básica e invocación de una llamada 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();
    

    El objeto SOAPCall posee un miembro llamado transportURI que es el URI de la localización a donde se debe enviar la llamada SOAP. El método encode() necesita el nombre del método a llamar en el servicio web, su namespaceURI , el número de SOAPParameters pasados y un array de SOAPParameters que contendrá todos los parámetros. Todos estos parámetros pueden conocerse en el fichero WSDL del servicio web, el cual será explicado en la sección de ejemplos.

    Los parámetros SOAP son creados usando el objeto SOAPParameter. Son pares de nombre/valor que son pasados al servicio web.

    Figura 2: Crear un parámetro SOAP

    var param = new SOAPParameter();
    param.name = "translationmode";
    param.value = "en_fr";
    

    Manejar una respuesta

    Una vez invoke() ha sido llamado, Gecko genera el contenedor SOAP y lo envía al URI especificado. Como la petición es síncrona, la respuesta es el valor devuelto desde invoke().

    Figura 3 : Manejar la respuesta de una llamada SOAP

    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);
    }
    

    El valor devuelto desde invoke() se guarda y comprueba en el miembro fault. Si éste existe, entonces ocurrió un error en el servicio web y el mensaje de error se guarda en fault.faultString. Si fault no existe, se puede llamar a la función getParameters() del objeto retornado para obtener los SOAPParameters devueltos.

    Ejemplo

    El siguiente ejemplo utiliza un servicio web real, Bablfish, proporcionado por xmethods.net. El servicio web Babelfish permite la traducción entre varios idiomas. Toma como entrada dos parámetros: una cadena con formato "<idioma_original>_<idioma_destino>" y otra cadena con el texto a traducir. El fichero WSDL para el servicio web de Bablfish está disponible aquí y contiene toda la información necesaria para configurar y hacer una llamada SOAP de bajo nivel al servicio web.

    El primer paso es conocer la localización del servicio web, la cual será el valor del miembro transportURI de SOAPCall. Esto se puede sacar del elemento service del WSDL, concretamente del atributo location de soap:address.

    Figura 4 : Obtener la localización del servicio web a partir de su WSDL

    WSDL:
      <service name="BabelFishService">
        <documentation>
          Translates text of up to 5k in length, between a variety of languages.
        </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";
      ...
    

    El siguiente paso es el más complicado: conocer exactamente qué parámetros espera recibir el servicio web. El servicio web de Babelfish sólo tiene un método, "Babelfish", el cual está representado en el WSDL en las etiquetas operation y que son hijas del elemento portType. Cada operation del WSDL tiene dos hijos: los elementos input y output, los cuales contienen el tipo esperado. Los tipos están definidos en los elementos message de los cuales hay dos: BabelFishRequest, que es lo que va a ser pasado al servicio web y babelFishResponse, que es el tipo devuelto.

    BabelFish espera recibir dos parámetros de entrada: translationmode y sourcedata. El ejemplo mostrado en la figura 5 traducirá la cadena "I am" del inglés al francés.

    Figura 5 : Estableciendo los parámetros necesarios

    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];
    

    Luego, es hora de configurar e invocar el objeto SOAPCall. "BabelFish" es el método usado por el ejemplo para el servicio web. El siguiente parámetro es el espacio de nombres que se espera para pasárselo al servicio web para el método BabelFish.

    Esto se puede saber mirando el elemento binding del WSDL. El elemento binding tiene un hijo operation para el método BabelFish. El espacio de nombres necesarios es el valor del atributo namespace de soap:body dentro del elemento input.

    Figura 6 : Configurando el método encode

    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();
    

    Como muestra la figura 5, la respuesta del método de BabelFish ("BabelFishResponse") tiene un parámetro, concretamente una cadena de texto. Tras asegurarnos de que no se ha devuelto un error, el método getParameters() del objeto devuelto es usado para obtener un array de SOAPResponses. Dado que se espera un solo parámetro (el texto traducido), el método alert() será usado para mostrar dicha traducción.

    Figura 7 : Manejando la respuesta

    JavaScript:
      if(translation.fault){
        // error returned from the web service
        alert(translation.fault.faultString);
      } else {
        // we expect only one return SOAPParameter - the translated string.
        var response = new Array();
        response = translation.getParameters(false, {});
        alert("Translation: " + response[0].value);
      }
    

    Como se dijo en la introducción, las llamadas SOAP obedecen la política de acceso multidominio en los scripts.

    Existen dos formas de rodear la política de seguridad para hacer pruebas:

     
    1. Ejecuta el script en el disco local.

      Guarda el código localmente en tu disco duro.

      El modelo de seguridad multidomino no afecta al código ejecutado desde el disco duro local.

    2. Habilita el acceso multidominio

      Se puede saltar la comprobación multidominio estableciendo una opción como se explica en el artículo Bypassing Security Restrictions and Signing Code y añadiéndolo al comando JavaScript para decirle a la petición que ignore la comprobación multidominio.

      Tras sortear la comprobación, ejecuta el navegador y carga esta página con el ejemplo modificado. Te preguntará (mediante un cuadro de diálogo) los permisos para desactivar el multidominio (para esa sesión) para la función generadora de la llamada SOAP. El único cambio realizado ha sido añadir netscape.security.PrivilegeManager.enablePrivilege("UniversalBrowserRead"); a la función que genera la llamada SOAP.

    Figura 8 : Código final - Ejemplo local, Ejemplo multidominio

    JavaScript:
      var babelFishCall = new SOAPCall();
      babelFishCall.transportURI = "http://services.xmethods.net:80/perl/soaplite.cgi";
    
      // SOAP params
      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];
    
      babelFishCall.encode(0, "BabelFish", "urn:xmethodsBabelFish", 0, null, myParamArray.length, myParamArray);
    
      var translation = babelFishCall.invoke();
    
      if(translation.fault){
        // error returned from the web service
        alert(translation.fault.faultString);
      } else {
       // we expect only one return SOAPParameter - the translated string.
       var response = new Array();
       response = translation.getParameters(false, {});
       alert("Translation: " + response[0].value);
     }
    

    Tras la pista del contenedor Soap

    Aquí se muestra un volcado HTTP (usando la aplicación multiplataforma Ethereal) de lo que realmente se envía y se recibe cuando se ejecuta el ejemplo:

    Figura 9 : Volcado HTTP

    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& (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>
    

    Recursos

    SOAP Scripts in Mozilla por Ray Whitmer
    Using the Mozilla SOAP API por Scott Andrew LePera and Apple Developer Connection.
    The Latest w3.org SOAP Specification
    Calling SOAP Servers from JS in Mozilla OnLamp.com article by Zachary Kessin
    SOAPCall documentation on XULPlanet.com
    SOAPResponse documentation on XULPlanet.com

    Información del documento original

     

    Etiquetas y colaboradores del documento

    Contributors to this page: Jorolo, Superruzafa, teoli
    Última actualización por: teoli,