Node.js: comment utiliser le service Web XML SOAP

99

Je me demande quelle est la meilleure façon de consommer le service Web SOAP XML avec node.js

Merci!

COULEUR BLANCHE
la source
Si vous utilisez node-soap et avez compris comment l'utiliser, pourriez-vous m'aider à créer un wsdl. Existe-t-il un générateur ou un bon tutoriel pour écrire le fichier wsdl. stackoverflow.com/questions/32480481/…
Andi Giga
Si vous avez besoin d'un exemple pour l'appel de service .NET WCF, vérifiez ma réponse stackoverflow.com/a/63351804/1370029
Aliaksei Maniuk

Réponses:

83

Vous n'avez pas beaucoup d'options.

Vous voudrez probablement utiliser l'un des:

Scripter juteux
la source
3
Merci. ayant des problèmes avec l'installation de node-soap car échec de l'installation de node-expat = (
WHITECOLOR
Vous aurez besoin d'en-têtes de développement d'expatriés pour le construire
Juicy Scripter
J'ai trouvé que le problème a été dit à propos des en-têtes, mais je ne sais pas où dois-je le trouver où dois-je le mettre à compiler, pouvez-vous expliquer, s'il vous plaît?
WHITECOLOR
1
Vous pouvez probablement les obtenir via des outils de gestion de paquets pour votre système d'exploitation. Sur Ubuntu par exemplesudo apt-get install libexpat1-dev
Juicy Scripter
1
@RobertBroden, merci pour la mise à jour. Veuillez la prochaine fois, modifier la réponse (ou suggérer une modification)!
Juicy Scripter
31

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 requête de nœud ( https://github.com/mikeal/request ) pour former un message xml d'entrée pour envoyer (POST) la requête au service Web (notez que les mécanismes de création de modèles javascript standard 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 cela devrait fonctionner sans problème

tmanolatos
la source
4
Malheureusement, c'est la méthode la plus fiable pour interagir avec SOAP avec Node.js. Je n'ai pas encore trouvé une seule bibliothèque de savon qui fasse correctement des demandes de savon sur la poignée d'API que je dois utiliser.
AlbertEngelB
1
100% sale, mais m'a amené aux résultats)))
markkillah
que voulez-vous tous dire avec pour former exactement le xml?
timaschew
oui, je peux encore le confirmer, aucune des bibliothèques mentionnées ci-dessus ne fonctionne parfaitement.
someUser
Je pense que "Form input xml" signifie simplement donner un Content-Type de "text / xml"
SSH ce
22

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

Ma demande ne fonctionnait pas node-soapet il n'y a pas de support pour ce module au-delà du support payant, qui dépassait mes ressources. J'ai donc 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 projectet téléchargé mon fichier wsdl_file.xml.
  4. Dans le navigateur, j'ai développé l'un des services et j'ai fait un clic droit sur la demande et j'ai cliqué sur Show Request Editor.

De là, je pourrais envoyer une demande et m'assurer que cela fonctionnait et je pourrais également utiliser le RawouHTML données 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 ce qui suit node request:

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);
jtlindsey
la source
merci @jtlindsey. Mais j'obtiens la méthode 405 non autorisée en tant que response.statusCode, response.statusMessage. Par hasard, savez-vous comment résoudre ce problème?
Sujoy
Un problème est survenu avec mon URL. J'utilisais l'URL d'origine au lieu du point de terminaison généré par SOAPUI. Merci pour le code ci-dessus.
Sujoy
17

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

Créez un serveur de nœuds appelé server.jsqui définira le service soap à utiliser par un client distant. Ce service de savon calcule l'indice de masse corporelle en fonction du poids (kg) et de la taille (m).

const soap = require('soap');
const express = require('express');
const 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
 */
const service = {
  BMI_Service: {
    BMI_Port: {
      calculateBMI(args) {
        //console.log(Date().getFullYear())
        const year = new Date().getFullYear();
        const n = args.weight / (args.height * args.height);
        console.log(n);
        return { bmi: n };
      }
    }
  }
};
// xml data is extracted from wsdl file created
const xml = require('fs').readFileSync('./bmicalculator.wsdl', 'utf8');
//create an express server and pass it to a soap server
const server = app.listen(3030, function() {
  const host = '127.0.0.1';
  const port = server.address().port;
});
soap.listen(server, '/bmicalculator', service, xml);

Ensuite, créez un client.jsfichier qui consommera 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 de SOAP.

const express = require('express');
const soap = require('soap');
const url = 'http://localhost:3030/bmicalculator?wsdl';
const 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 d'échange de données basé sur XML qui définit comment accéder à un service Web distant. Appelez votre fichier wsdlbmicalculator.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

Kim .J
la source
1
Merci beaucoup. Cependant, j'ai dû supprimer "res.send (response);" du client et "` "à la dernière ligne du fichier serveur.
Subhashi
13

Le moyen le plus simple que j'ai trouvé pour simplement envoyer 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 le 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, plutôt que d'envoyer du XML brut, utilisez l'une des bibliothèques Node.js. J'aime node-soap .

Demi-arrêt
la source
1
#Halfstop, pourriez-vous s'il vous plaît me dire comment faire une requête POST en utilisant node-soap?
Abhishek saini
@Abhisheksaini l'exemple ci-dessus est un post.
Halfstop
@Halfstop Veuillez me dire comment inclure SOAPAction dans la demande.
Sohail
12

Selon le nombre de terminaux dont vous avez besoin, il peut être plus facile de le faire manuellement.

J'ai essayé 10 bibliothèques "soap nodejs", je le fais enfin manuellement.

dam1
la source
J'ai essayé node-soap pour accéder à la route wsdl mais cela ne fonctionne pas, je continue à recevoir une erreur bien que la même chose fonctionne en php Pouvez-vous répondre à ma question sur la façon dont vous l'avez fait stackoverflow.com/questions/39943122/…
Ammar Ajmal
8

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

Les problèmes viennent généralement du fait que les programmeurs ne recherchent pas beaucoup ce dont l'API distante a besoin pour se connecter ou s'authentifier.

Par exemple, PHP renvoie automatiquement les cookies des en-têtes HTTP, mais lors de l'utilisation du package 'node', il doit être défini explicitement (par exemple par le package 'soap-cookie') ...

smentek
la source
l'utilisation de soap-cookie m'a aidé à contourner un problème d'authentification que j'avais dans le nœud, merci beaucoup!
nicolasdaudin
5

J'ai utilisé le module node net pour ouvrir une socket sur le webservice.

/* 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;
    }

Analyser la réponse de savon, 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

Vince Lowe
la source
1
pourquoi feriez-vous cela au lieu d'utiliser le module http?
Will Munn
0

Ajout à la solution de Kim .J : vous pouvez ajouter preserveWhitespace=trueafin d'éviter une erreur d'espace blanc. Comme ça:

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

Vous pouvez également utiliser wsdlrdr. EasySoap est essentiellement une réécriture de wsdlrdr avec quelques méthodes supplémentaires. Attention, easysoap ne dispose pas de la méthode getNamespace disponible sur wsdlrdr.

allen_mxk686
la source
0

Pour ceux qui sont nouveaux SOAPet qui veulent une explication et un guide rapides, je recommande vivement cet article médiatique génial .

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

MajidJafari
la source
0

Si vous avez juste besoin d'une conversion unique, https://www.apimatic.io/dashboard?modal=transform vous permet de le faire en créant un compte gratuit (pas d'affiliation, cela a juste fonctionné pour moi).

Si vous vous transformez en Swagger 2.0, vous pouvez créer une librairie js avec

$ wget https://repo1.maven.org/maven2/io/swagger/codegen/v3/swagger-codegen-cli/3.0.20/swagger-codegen-cli-3.0.20.jar \
  -O swagger-codegen-cli.jar
$ java -jar swagger-codegen-cli.jar generate \
  -l javascript -i orig.wsdl-Swagger20.json -o ./fromswagger
marteler
la source