Je me demande quelle est la meilleure façon de consommer le service Web SOAP XML avec node.js
Merci!
Je me demande quelle est la meilleure façon de consommer le service Web SOAP XML avec node.js
Merci!
Réponses:
Vous n'avez pas beaucoup d'options.
Vous voudrez probablement utiliser l'un des:
node-soap
)sudo apt-get install libexpat1-dev
Je pense qu'une alternative serait de:
Oui, c'est une approche plutôt sale et de bas niveau mais cela devrait fonctionner sans problème
Si node-soap
cela ne fonctionne pas pour vous, utilisez simplement le node
request
module, puis convertissez le xml en json si nécessaire.
Ma demande ne fonctionnait pas node-soap
et 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:
curl http://192.168.0.28:10005/MainService/WindowsService?wsdl > wsdl_file.xml
File > New Soap project
et téléchargé mon fichier wsdl_file.xml
.Show Request Editor
.De là, je pourrais envoyer une demande et m'assurer que cela fonctionnait et je pourrais également utiliser le Raw
ouHTML
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);
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.js
qui 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.js
fichier 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
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 .
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.
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') ...
Vous pouvez également consulter le npm d'easysoap - https://www.npmjs.org/package/easysoap -ou- certains d'entre eux: https://nodejsmodules.org/tags/soap
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
Ajout à la solution de Kim .J : vous pouvez ajouter preserveWhitespace=true
afin d'éviter une erreur d'espace blanc. Comme ça:
soap.CreateClient(url,preserveWhitespace=true,function(...){
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.
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