Node.js: як використовувати веб-службу SOAP XML


99

Цікаво, який найкращий спосіб використовувати веб-службу SOAP XML із node.js

Дякую!


Якщо ви використовуєте node-soap та придумали, як ним користуватися, не могли б ви допомогти мені зі створенням wsdl. Чи є генератор або хороший підручник, як писати wsdl. stackoverflow.com/questions/32480481/…
Анді Гіга,

Якщо вам потрібен приклад для виклику служби .NET WCF, перевірте мою відповідь stackoverflow.com/a/63351804/1370029
Aliaksei Maniuk

Відповіді:


83

У вас не так багато варіантів.

Можливо, вам захочеться скористатися одним із:


3
Дякую. виникають проблеми із встановленням node-soap, оскільки помилка встановлення node-expat = (
WHITECOLOR

Для його створення вам знадобляться заголовки розробників емігрантів
Juicy Scripter

Я знайшов проблему, про яку говорили про заголовки, але я не знаю, де мені її взяти, де я повинен її скласти, не могли б ви пояснити, будь ласка?
WHITECOLOR

1
Можливо, ви можете отримати їх за допомогою інструментів управління пакетами для вашої ОС. Наприклад, на Ubuntusudo apt-get install libexpat1-dev
Juicy Scripter

1
@RobertBroden, дякую за оновлення. Будь ласка, наступного разу продовжте редагувати відповідь (або запропонуйте змінити)!
Juicy Scripter

31

Я думаю, що альтернативою було б:

  • використовуйте такий інструмент, як SoapUI ( http://www.soapui.org ) для запису вхідних та вихідних xml-повідомлень
  • використовувати запит вузла ( https://github.com/mikeal/request ) для формування вхідного повідомлення xml для надсилання (POST) запиту веб-службі (зверніть увагу, що стандартні механізми шаблонування javascript, такі як ejs ( http://embeddedjs.com / ) або вуса ( https://github.com/janl/mustache.js ) можуть вам тут допомогти) і нарешті
  • використовуйте синтаксичний аналізатор XML для десериалізації даних відповідей на об’єкти JavaScript

Так, це досить брудний і низькорівневий підхід, але він повинен працювати без проблем


4
На жаль, це найнадійніший метод взаємодії з SOAP із Node.js. Я ще не знайшов жодної бібліотеки мила, яка належним чином робить запити на мило для декількох API, якими я повинен користуватися.
AlbertEngelB

1
100% брудний, але привів мене до результатів)))
markkillah

що ви все маєте на увазі з точним формуванням вхідного xml`?
timaschew

так, можу ще підтвердити, жодна з вищезгаданих бібліотек не працює ідеально.
someUser

Я думаю, що "введення форми xml" означає просто надання типу вмісту "text / xml"
SSH цього

22

Якщо у вас node-soapне виходить, просто використовуйте node requestмодуль, а потім перетворіть xml на json, якщо це потрібно.

З моїм запитом не працювали, node-soapі для цього модуля немає підтримки, крім платної підтримки, яка була за межами моїх ресурсів. Тож я зробив наступне:

  1. завантажив SoapUI на свою машину Linux.
  2. скопіював файл WSDL xml у локальний файл
    curl http://192.168.0.28:10005/MainService/WindowsService?wsdl > wsdl_file.xml
  3. У SoapUI я зайшов File > New Soap projectі завантажив свій wsdl_file.xml.
  4. У навігаторі я розширив одну із служб і клацнув правою кнопкою миші запит і натиснув Show Request Editor.

Звідти я міг відправити запит і переконатися, що він працює, а також міг використати дані Rawабо, HTMLщоб допомогти мені створити зовнішній запит.

Сирець із 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);

дякую @jtlindsey. Але я отримую метод 405, не дозволений як response.statusCode, response.statusMessage. Ви випадково знаєте, як це виправити?
Суджой

Виникла проблема з моєю URL-адресою. Я використовував вихідну URL-адресу замість кінцевої точки, створеної SOAPUI. Дякуємо за наведений вище код.
Суджой

17

Мені вдалося використовувати мило, 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>

Сподіваюся, це допомагає


1
Дуже дякую. Однак мені довелося видалити "res.send (відповідь);" від клієнта та "` "в останньому рядку файлу сервера.
Субхасі

13

Найпростіший спосіб просто надіслати необроблений 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. Мені подобається вузол-мило .


1
#Halfstop, підкажіть, будь ласка, як зробити запит POST за допомогою node-soap?
Абхішек Сайні 02

@Abhisheksaini наведений вище приклад - це допис.
Зупинка

@Halfstop Будь ласка, скажіть мені, як включити SOAPAction до запиту.
Сохайл

12

Залежно від кількості потрібних вам кінцевих точок може бути простіше зробити це вручну.

Я спробував 10 бібліотек "soap nodejs", нарешті, роблю це вручну.


Я спробував node-soap для доступу до маршруту wsdl, але це не працює, я постійно отримую помилку, хоча те саме працює в php. Чи можете ви відповісти на моє запитання про те, як ви це зробили? Stackoverflow.com/questions/39943122/…
Аммар Аймаль

8

Я успішно використав пакет "мило" ( https://www.npmjs.com/package/soap ) у більш ніж 10 веб-програмах для відстеження (Tradetracker, Bbelboon, Affilinet, Webgains, ...).

Зазвичай проблеми виникають внаслідок того, що програмісти не надто досліджують, що потрібно віддаленому API для підключення або автентифікації.

Наприклад, PHP автоматично перепродає файли cookie з заголовків HTTP, але при використанні пакету 'node' він повинен бути чітко встановлений (наприклад, пакетом 'soap-cookie') ...


використання мильного файлу cookie допомогло мені обійти проблему автентифікації, яку я мав у вузлі, дякую!
Ніколасдаудін,


5

Я використав модуль node net, щоб відкрити сокет для веб-служби.

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

Сподіваюся, це комусь допомагає


1
чому ви робите це замість використання модуля http?
Уілл Манн

0

Додавання до рішення Kim .J : ви можете додати preserveWhitespace=true, щоб уникнути пробілу. Подобається це:

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

0

Ви також можете використовувати wsdlrdr. EasySoap в основному переписує wsdlrdr за допомогою деяких додаткових методів. Будьте обережні, щоб у easysoap не було методу getNamespace, який доступний у wsdlrdr.


0

Тим, хто новачок у роботі SOAPта бажає швидкого пояснення та керівництва, я настійно рекомендую цю дивовижну середню статтю .

Ви також можете використовувати node-soap пакет , за допомогою цього простого підручника .


0

Якщо вам просто потрібна одноразова конверсія, 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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.