Je me demande quel est le meilleur moyen de consommer le service Web XML SOAP avec node.js
Merci!
Vous n'avez pas beaucoup d'options.
Vous voudrez probablement utiliser l'un des:
node-soap
)Je pense qu'une alternative serait de:
Oui, c'est une approche plutôt sale et de bas niveau mais elle devrait fonctionner sans problèmes
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 .
Si node-soap
ne fonctionne pas pour vous, utilisez simplement le module node
request
, 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:
curl http://192.168.0.28:10005/MainService/WindowsService?wsdl > wsdl_file.xml
File > New Soap project
et ai téléchargé mon wsdl_file.xml
.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 node
request
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);
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
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.
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') ...
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
Vous pouvez également consulter easysoap npm - https://www.npmjs.org/package/easysoap - ou quelques-uns de ceux-ci: https: // nodejsmodules. org/tags/soap
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(...){
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.