Интересно, как лучше всего использовать веб-службу SOAP XML с помощью node.js
Спасибо!
Интересно, как лучше всего использовать веб-службу SOAP XML с помощью node.js
Спасибо!
Ответы:
У вас не так много вариантов.
Вероятно, вы захотите использовать одно из:
node-soap
)sudo apt-get install libexpat1-dev
Думаю, альтернативой было бы:
Да, это довольно грязный и низкоуровневый подход, но он должен работать без проблем.
Если у node-soap
вас не работает, просто используйте node
request
модуль, а затем при необходимости конвертируйте xml в json.
Мой запрос не работал, node-soap
и для этого модуля нет поддержки, кроме платной поддержки, которая была вне моих ресурсов. Итак, я сделал следующее:
curl http://192.168.0.28:10005/MainService/WindowsService?wsdl > wsdl_file.xml
File > New Soap project
и загрузил свой wsdl_file.xml
.Show Request Editor
.Оттуда я мог отправить запрос и убедиться, что он работает, а также использовать данные Raw
или, HTML
чтобы помочь мне создать внешний запрос.
Raw из SoapUI по моему запросу
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 из 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>
Я использовал это для создания следующего 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);
Мне удалось использовать мыло, wsdl и Node.js Вам нужно установить мыло с npm install soap
Создайте сервер узла, server.js
который будет определять мыльную службу, которая будет использоваться удаленным клиентом. Этот мыльный сервис рассчитывает индекс массы тела на основе веса (кг) и роста (м).
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);
Затем создайте client.js
файл, который будет использовать службу мыла, определяемую server.js
. Этот файл предоставит аргументы для мыльной службы и вызовет URL-адрес с портами и конечными точками службы 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);
}
});
}
});
Ваш файл wsdl - это протокол на основе xml для обмена данными, который определяет, как получить доступ к удаленной веб-службе. Назовите ваш файл 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>
Надеюсь, поможет
Самый простой способ, который я нашел, просто отправить необработанный XML в службу SOAP с помощью Node.js, - это использовать реализацию Node.js http. Это выглядит так.
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();
Вы бы определили переменную xml как необработанный xml в форме строки.
Но если вы просто хотите взаимодействовать со службой SOAP через Node.js и делать регулярные вызовы SOAP, а не отправлять необработанный XML, используйте одну из библиотек Node.js. Мне нравится узел-мыло .
В зависимости от количества необходимых конечных точек может быть проще сделать это вручную.
Я пробовал 10 библиотек «мыло nodejs», наконец, делаю это вручную.
Я успешно использовал пакет «мыло» ( https://www.npmjs.com/package/soap ) на более чем 10 отслеживающих WebApis (Tradetracker, Bbelboon, Affilinet, Webgains, ...).
Проблемы обычно возникают из-за того, что программисты не уделяют много внимания тому, что удаленному API нужно для подключения или аутентификации.
Например, PHP автоматически пересылает файлы cookie из заголовков HTTP, но при использовании пакета 'node' он должен быть явно установлен (например, пакетом 'soap-cookie') ...
Вы также можете посмотреть файл easysoap npm - https://www.npmjs.org/package/easysoap или некоторые из них: https://nodejsmodules.org/tags/soap
Я использовал сетевой модуль узла, чтобы открыть сокет для веб-службы.
/* 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);
}
});
Отправить запросы на мыло
/* 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;
}
Разобрать ответ мыла, я использовал модуль - 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();
}
}
});
Надеюсь, это кому-то поможет
Добавление к решению Kim .J : вы можете добавить preserveWhitespace=true
, чтобы избежать ошибки пробела. Как это:
soap.CreateClient(url,preserveWhitespace=true,function(...){
Вы также можете использовать wsdlrdr. EasySoap в основном переписывает wsdlrdr с некоторыми дополнительными методами. Будьте осторожны, у easysoap нет метода getNamespace, доступного на wsdlrdr.
Для тех, кто новичок SOAP
и хочет получить быстрое объяснение и руководство, я настоятельно рекомендую эту замечательную статью среднего размера .
Вы также можете использовать node-soap
пакет с помощью этого простого руководства .
Если вам просто нужно одноразовое преобразование, https://www.apimatic.io/dashboard?modal=transform позволяет сделать это, создав бесплатную учетную запись (без привязки, это просто сработало для меня).
Если вы трансформируетесь в Swagger 2.0, вы можете создать js lib с
$ 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