web-dev-qa-db-fra.com

Node.js: comment consommer SOAP Service web XML

Je me demande quel est le meilleur moyen de consommer le service Web XML SOAP avec node.js

Merci!

83
WHITECOLOR

Vous n'avez pas beaucoup d'options.

Vous voudrez probablement utiliser l'un des:

72
Juicy Scripter

Je pense qu'une alternative serait de:

  • utilisez un outil tel que SoapUI ( http://www.soapui.org ) pour enregistrer les messages XML d'entrée et de sortie
  • utilisez la demande de noeud ( https://github.com/mikeal/request _) pour former un message XML d'entrée afin d'envoyer (POST) la demande au service Web (notez que les mécanismes standard de création de modèles JavaScript, tels que ejs http://embeddedjs.com/ ) ou moustache ( https://github.com/janl/mustache.js ) pourrait vous aider ici) et enfin
  • utiliser un analyseur XML pour désérialiser les données de réponse en objets JavaScript

Oui, c'est une approche plutôt sale et de bas niveau mais elle devrait fonctionner sans problèmes

30
tmanolatos

Le moyen le plus simple que j'ai trouvé d'envoyer simplement du XML brut à un service SOAP à l'aide de Node.js est d'utiliser l'implémentation http Node.js. Ça ressemble à ça.

var http = require('http');
var http_options = {
  hostname: 'localhost',
  port: 80,
  path: '/LocationOfSOAPServer/',
  method: 'POST',
  headers: {
    'Content-Type': 'application/x-www-form-urlencoded',
    'Content-Length': xml.length
  }
}

var req = http.request(http_options, (res) => {
  console.log(`STATUS: ${res.statusCode}`);
  console.log(`HEADERS: ${JSON.stringify(res.headers)}`);
  res.setEncoding('utf8');
  res.on('data', (chunk) => {
    console.log(`BODY: ${chunk}`);
  });

  res.on('end', () => {
    console.log('No more data in response.')
  })
});

req.on('error', (e) => {
  console.log(`problem with request: ${e.message}`);
});

// write data to request body
req.write(xml); // xml would have been set somewhere to a complete xml document in the form of a string
req.end();

Vous auriez défini la variable xml comme xml brut sous la forme d'une chaîne.

Mais si vous souhaitez simplement interagir avec un service SOAP via Node.js et effectuer des appels SOAP réguliers, par opposition à l'envoi de fichiers xml bruts, utilisez l'une des bibliothèques Node.js. J'aime node-soap .

14
Halfstop

Si node-soap ne fonctionne pas pour vous, utilisez simplement le module noderequest, puis convertissez le xml en json si nécessaire. 

Ma demande ne fonctionnait pas avec node-soap et ce module ne prend en charge que le support payant, qui dépassait mes ressources. Alors j'ai fait ce qui suit: 

  1. téléchargé SoapUI sur ma machine Linux.
  2. copié le XML WSDL dans un fichier local
    curl http://192.168.0.28:10005/MainService/WindowsService?wsdl > wsdl_file.xml
  3. Dans SoapUI je suis allé à File > New Soap project et ai téléchargé mon wsdl_file.xml.
  4. Dans le navigateur, j'ai développé l'un des services et cliqué avec le bouton droit de la souris sur la demande, puis sur Show Request Editor.

À partir de là, je pouvais envoyer une demande et m'assurer que cela fonctionnait. Je pouvais également utiliser les données Raw ou HTML pour m'aider à créer une demande externe.

Raw de SoapUI pour ma demande

POST http://192.168.0.28:10005/MainService/WindowsService HTTP/1.1
Accept-Encoding: gzip,deflate
Content-Type: text/xml;charset=UTF-8
SOAPAction: "http://Main.Service/AUserService/GetUsers"
Content-Length: 303
Host: 192.168.0.28:10005
Connection: Keep-Alive
User-Agent: Apache-HttpClient/4.1.1 (Java 1.5)

XML de SoapUI

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:qtre="http://Main.Service">
   <soapenv:Header/>
   <soapenv:Body>
      <qtre:GetUsers>
         <qtre:sSearchText></qtre:sSearchText>
      </qtre:GetUsers>
   </soapenv:Body>
</soapenv:Envelope> 

J'ai utilisé ce qui précède pour construire la noderequest suivante:

var request = require('request');
let xml =
`<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:qtre="http://Main.Service">
   <soapenv:Header/>
   <soapenv:Body>
      <qtre:GetUsers>
         <qtre:sSearchText></qtre:sSearchText>
      </qtre:GetUsers>
   </soapenv:Body>
</soapenv:Envelope>`

var options = {
  url: 'http://192.168.0.28:10005/MainService/WindowsService?wsdl',
  method: 'POST',
  body: xml,
  headers: {
    'Content-Type':'text/xml;charset=utf-8',
    'Accept-Encoding': 'gzip,deflate',
    'Content-Length':xml.length,
    'SOAPAction':"http://Main.Service/AUserService/GetUsers"
  }
};

let callback = (error, response, body) => {
  if (!error && response.statusCode == 200) {
    console.log('Raw result', body);
    var xml2js = require('xml2js');
    var parser = new xml2js.Parser({explicitArray: false, trim: true});
    parser.parseString(body, (err, result) => {
      console.log('JSON result', result);
    });
  };
  console.log('E', response.statusCode, response.statusMessage);  
};
request(options, callback);
13
jtlindsey

J'ai réussi à utiliser soap, wsdl et Node.jsVous devez installer soap avec npm install soap

Créez un serveur de nœud appelé server.js qui définira le service soap devant être utilisé par un client distant. Ce service calcule l'indice de masse corporelle en fonction du poids (kg) et de la taille (m).

var soap = require('soap');
var express = require('express');
var app = express();
/** 
-this is remote service defined in this file, that can be accessed by clients, who will supply args
-response is returned to the calling client
-our service calculates bmi by dividing weight in kilograms by square of height in metres
**/
var service = {
    BMI_Service : {
        BMI_Port :{
            calculateBMI:function(args){
                //console.log(Date().getFullYear())
                var year = new Date().getFullYear();
                var n = (args.weight)/(args.height*args.height);
                console.log(n);
                return {bmi: n};
            }
        }
   }
}
// xml data is extracted from wsdl file created
var xml = require('fs').readFileSync('./bmicalculator.wsdl','utf8');
//create an express server and pass it to a soap server
var server = app.listen(3030,function(){
var Host = "127.0.0.1";
var port = server.address().port;
});
`soap.listen(server,'/bmicalculator',service,xml);

Ensuite, créez un fichier client.js qui utilisera le service soap défini par server.js. Ce fichier fournira des arguments pour le service soap et appellera l'URL avec les ports de service et les points de terminaison SOAP.

var express = require('express');
var soap = require('soap');
var url = "http://localhost:3030/bmicalculator?wsdl";
var args = {weight:65.7,height:1.63};
soap.createClient(url,function(err,client){
if(err)
console.error(err);
else {
client.calculateBMI(args,function(err,response){
if(err)
console.error(err);
else {
console.log(response);
res.send(response);
}
})
}
});

Votre fichier WSDL est un protocole XML d'échange de données qui définit le mode d'accès à un service Web distant. Appelez votre fichier wsdl bmicalculator.wsdl

<definitions name="HelloService"
targetNamespace="http://www.examples.com/wsdl/HelloService.wsdl"
xmlns="http://schemas.xmlsoap.org/wsdl/"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:tns="http://www.examples.com/wsdl/HelloService.wsdl"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">

<message name="getBMIRequest">
<part name="weight" type="xsd:float"/>
<part name="height" type="xsd:float"/>
</message>

<message name="getBMIResponse">
<part name="bmi" type="xsd:float"/>
</message>

<portType name="Hello_PortType">
<operation name="calculateBMI">
<input message="tns:getBMIRequest"/>
<output message="tns:getBMIResponse"/>
</operation>
</portType>

<binding name="Hello_Binding" type="tns:Hello_PortType">
<soap:binding style="rpc"
transport="http://schemas.xmlsoap.org/soap/http"/>
<operation name="calculateBMI">
<soap:operation soapAction="calculateBMI"/>
<input>
<soap:body
encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
namespace="urn:examples:helloservice"
use="encoded"/>
</input>
<output>
<soap:body
encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
namespace="urn:examples:helloservice"
use="encoded"/>
</output>
</operation>
</binding>

<service name="BMI_Service">
<documentation>WSDL File for HelloService</documentation>
<port binding="tns:Hello_Binding" name="BMI_Port">
<soap:address
location="http://localhost:3030/bmicalculator/" />
</port>
</service>
</definitions>

J'espère que ça aide

12
Kim .J

En fonction du nombre de points de terminaison dont vous avez besoin, il peut être plus facile de le faire manuellement.

J'ai essayé 10 bibliothèques "soap nodejs" Je l'ai finalement fait manuellement. 

9
dam1

J'ai utilisé avec succès le paquet "soap" ( https://www.npmjs.com/package/soap ) sur plus de 10 WebApis de suivi (Tradetracker, Bbelboon, Affilinet, Webgains, ...). 

Les problèmes viennent généralement du fait que les programmeurs n’enquêtent pas beaucoup sur ce dont l’API distante a besoin pour se connecter ou s’authentifier. 

Par exemple, PHP renvoie automatiquement les cookies à partir des en-têtes HTTP, mais lorsque vous utilisez le package 'node', vous devez le définir explicitement (par exemple, avec le package 'soap-cookie') ... 

8
smentek

J'ai utilisé le module de nœud net pour ouvrir un socket sur le service Web.

/* on Login request */
socket.on('login', function(credentials /* {username} {password} */){   
    if( !_this.netConnected ){
        _this.net.connect(8081, '127.0.0.1', function() {
            logger.gps('('+socket.id + ') '+credentials.username+' connected to: 127.0.0.1:8081');
            _this.netConnected = true;
            _this.username = credentials.username;
            _this.password = credentials.password;
            _this.m_RequestId = 1;
            /* make SOAP Login request */
            soapGps('', _this, 'login', credentials.username);              
        });         
    } else {
        /* make SOAP Login request */
        _this.m_RequestId = _this.m_RequestId +1;
        soapGps('', _this, 'login', credentials.username);          
    }
});

Envoyer des demandes de savon

/* SOAP request func */
module.exports = function soapGps(xmlResponse, client, header, data) {
    /* send Login request */
    if(header == 'login'){
        var SOAP_Headers =  "POST /soap/gps/login HTTP/1.1\r\nHost: soap.example.com\r\nUser-Agent: SOAP-client/SecurityCenter3.0\r\n" +
                            "Content-Type: application/soap+xml; charset=\"utf-8\"";        
        var SOAP_Envelope=  "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
                            "<env:Envelope xmlns:env=\"http://www.w3.org/2003/05/soap-envelope\" xmlns:SOAP-ENC=\"http://www.w3.org/2003/05/soap-encoding\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:n=\"http://www.example.com\"><env:Header><n:Request>" +
                            "Login" +
                            "</n:Request></env:Header><env:Body>" +
                            "<n:RequestLogin xmlns:n=\"http://www.example.com.com/gps/soap\">" +
                            "<n:Name>"+data+"</n:Name>" +
                            "<n:OrgID>0</n:OrgID>" +                                        
                            "<n:LoginEntityType>admin</n:LoginEntityType>" +
                            "<n:AuthType>simple</n:AuthType>" +
                            "</n:RequestLogin></env:Body></env:Envelope>";

        client.net.write(SOAP_Headers + "\r\nContent-Length:" + SOAP_Envelope.length.toString() + "\r\n\r\n");
        client.net.write(SOAP_Envelope);
        return;
    }

Parse soap response, j'ai utilisé le module - xml2js

var parser = new xml2js.Parser({
    normalize: true,
    trim: true,
    explicitArray: false
});
//client.net.setEncoding('utf8');

client.net.on('data', function(response) {
    parser.parseString(response);
});

parser.addListener('end', function( xmlResponse ) {
    var response = xmlResponse['env:Envelope']['env:Header']['n:Response']._;
    /* handle Login response */
    if (response == 'Login'){
        /* make SOAP LoginContinue request */
        soapGps(xmlResponse, client, '');
    }
    /* handle LoginContinue response */
    if (response == 'LoginContinue') {
        if(xmlResponse['env:Envelope']['env:Body']['n:ResponseLoginContinue']['n:ErrCode'] == "ok") {           
            var nTimeMsecServer = xmlResponse['env:Envelope']['env:Body']['n:ResponseLoginContinue']['n:CurrentTime'];
            var nTimeMsecOur = new Date().getTime();
        } else {
            /* Unsuccessful login */
            io.to(client.id).emit('Error', "invalid login");
            client.net.destroy();
        }
    }
});

J'espère que ça aide quelqu'un

5
Vince Lowe

Vous pouvez également consulter easysoap npm - https://www.npmjs.org/package/easysoap - ou quelques-uns de ceux-ci: https: // nodejsmodules. org/tags/soap

_ { https://nodejsmodules.org/pkg/express-soap2json } _

5
euroblaze

Ajouter à la solution de Kim .J : vous pouvez ajouter preserveWhitespace=true afin d'éviter une erreur Whitespace. Comme ça:

soap.CreateClient(url,preserveWhitespace=true,function(...){
0
J.Aliaga

Vous pouvez également utiliser wsdlrdr. EasySoap est fondamentalement la réécriture de wsdlrdr avec quelques méthodes supplémentaires. Faites attention à ce que easysoap n’ait pas la méthode getNamespace disponible sur wsdlrdr.

0
user10152282

Pour ceux qui sont nouveaux dans SOAP et qui veulent une explication rapide et un guide, je recommande fortement ce moyen génial article .

Vous pouvez également utiliser node-soappackage , avec ce simple tutoriel .

0
MajidJafari