Node.js: jak korzystać z usługi sieciowej SOAP XML

99

Zastanawiam się, jaki jest najlepszy sposób korzystania z usługi sieciowej XML SOAP z node.js

Dzięki!

BIAŁY KOLOR
źródło
Jeśli używasz node-soap i zorientowałeś się, jak go używać, czy możesz mi pomóc w tworzeniu pliku wsdl. Czy istnieje generator lub dobry tutorial jak napisać wsdl. stackoverflow.com/questions/32480481/…
Andi Giga
Jeśli potrzebujesz przykładu dla wezwania serwisu .NET WCF, sprawdź moją odpowiedź stackoverflow.com/a/63351804/1370029
Aliaksei Maniuk

Odpowiedzi:

84

Nie masz tak wielu opcji.

Prawdopodobnie będziesz chciał użyć jednego z:

Juicy Scripter
źródło
3
Dzięki. mają problemy z instalacją węzła mydła, ponieważ nie powiodła się instalacja węzła-
ekspata
Aby go zbudować, będziesz potrzebować nagłówków programistycznych expat
Juicy Scripter
Znalazłem problem, o którym mówiono o nagłówkach, ale nie wiem, gdzie powinienem go znaleźć, gdzie powinienem go skompilować, czy możesz wyjaśnić, proszę?
WHITECOLOR
1
Prawdopodobnie możesz je zdobyć za pomocą narzędzi do zarządzania pakietami dla twojego systemu operacyjnego. Na przykład na Ubuntusudo apt-get install libexpat1-dev
Juicy Scripter
1
@RobertBroden, dzięki za aktualizację. Następnym razem przejdź dalej i edytuj odpowiedź (lub zasugeruj zmianę)!
Juicy Scripter
31

Myślę, że alternatywą byłoby:

Tak, jest to raczej brudne i niskopoziomowe podejście, ale powinno działać bez problemów

tmanolatos
źródło
4
Niestety, jest to najbardziej niezawodna metoda interakcji z SOAP w Node.js. Nie znalazłem jeszcze ani jednej biblioteki mydeł, która prawidłowo wysyła żądania mydła w kilku interfejsach API, których muszę używać.
AlbertEngelB,
1
100% brudne, ale doprowadziło mnie do rezultatów)))
markkillah
co wszyscy macie na myśli, tworząc dokładnie XML wejściowy?
timaschew
tak, nadal mogę potwierdzić, żadna z wyżej wymienionych bibliotek nie działa idealnie.
someUser
Myślę, że „Form input xml” oznacza po prostu podanie typu zawartości „text / xml”
SSH.
22

Jeśli node-soapto nie zadziała, po prostu użyj node requestmodule, a następnie przekonwertuj xml na json, jeśli to konieczne.

Moja prośba nie zadziałała node-soapi nie ma wsparcia dla tego modułu poza płatnym wsparciem, które było poza moimi zasobami. Więc zrobiłem co następuje:

  1. pobranych SoapUI na moim komputerze z systemem Linux.
  2. skopiował WSDL xml do pliku lokalnego
    curl http://192.168.0.28:10005/MainService/WindowsService?wsdl > wsdl_file.xml
  3. W SoapUI poszedłem File > New Soap projecti wrzuciłem mój wsdl_file.xml.
  4. W nawigatorze rozwinąłem jedną z usług, kliknąłem żądanie prawym przyciskiem myszy i kliknąłem Show Request Editor.

Stamtąd mogłem wysłać żądanie i upewnić się, że działa, a także mogę użyć danych Rawlub, HTMLaby pomóc mi zbudować żądanie zewnętrzne.

Surowy z SoapUI na moją prośbę

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 z 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> 

Użyłem powyższego do zbudowania następujących elementów 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
źródło
dzięki @jtlindsey. Ale otrzymuję metodę 405 niedozwoloną jako response.statusCode, response.statusMessage. Czy wiesz, jak to naprawić?
Sujoy
Wystąpił problem z moim adresem URL. Używałem oryginalnego adresu URL zamiast punktu końcowego wygenerowanego przez SOAPUI. Dzięki za powyższy kod.
Sujoy
17

Udało mi się użyć mydła, wsdl i Node.js, z którym trzeba zainstalować mydło npm install soap

Utwórz serwer węzłów o nazwie server.js, który zdefiniuje usługę mydła do wykorzystania przez klienta zdalnego. Ta usługa mydła oblicza wskaźnik masy ciała na podstawie wagi (kg) i wzrostu (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);

Następnie utwórz client.jsplik, który będzie zużywał usługę mydła zdefiniowaną przez server.js. Ten plik zawiera argumenty dla usługi mydła i wywołuje adres URL z portami usług i punktami końcowymi protokołu 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);
      }
    });
  }
});

Plik wsdl to oparty na XML protokół wymiany danych, który definiuje sposób uzyskiwania dostępu do zdalnej usługi internetowej. Wywołaj swój plik 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>

Mam nadzieję, że to pomoże

Kim .J
źródło
1
Dziękuję bardzo. Jednak musiałem usunąć "res.send (odpowiedź);" od klienta i "" "w ostatniej linii pliku serwera.
Subhashi
13

Najprostszym sposobem wysłania surowego XML do usługi SOAP przy użyciu Node.js jest użycie implementacji HTTP Node.js. To wygląda tak.

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();

Zdefiniowałbyś zmienną xml jako nieprzetworzony xml w postaci łańcucha.

Ale jeśli chcesz tylko współdziałać z usługą SOAP za pośrednictwem Node.js i wykonywać regularne wywołania SOAP, w przeciwieństwie do wysyłania surowego xml, użyj jednej z bibliotek Node.js. Lubię mydło do węzłów .

Halfstop
źródło
1
#Halfstop, czy mógłbyś mi powiedzieć, jak wykonać żądanie POST za pomocą węzła mydła?
Abhishek saini
@Abhisheksaini Powyższy przykład to post.
Halfstop
@ Halfstop Powiedz mi, jak uwzględnić SOAPAction w żądaniu.
Sohail
12

W zależności od liczby potrzebnych punktów końcowych może być łatwiej zrobić to ręcznie.

Wypróbowałem 10 bibliotek "mydło nodejs". Wreszcie robię to ręcznie.

dam1
źródło
Próbowałem węzła mydła dostępu trasę wsdl ale nie robi praca, ciśgle błąd chociaż samo działa w PHP może odpowiedzieć na moje pytanie o tym, jak to się stackoverflow.com/questions/39943122/...
Ammar Ajmal
8

Z powodzeniem użyłem pakietu „mydło” ( https://www.npmjs.com/package/soap ) na ponad 10 śledzących WebApis (Tradetracker, Bbelboon, Affilinet, Webgains, ...).

Problemy zwykle wynikają z faktu, że programiści nie badają zbyt wiele na temat tego, czego potrzebuje zdalny interfejs API w celu nawiązania połączenia lub uwierzytelnienia.

Na przykład PHP automatycznie ponownie wysyła pliki cookie z nagłówków HTTP, ale podczas korzystania z pakietu „node” musi być wyraźnie ustawione (na przykład przez pakiet „soap-cookie”) ...

smentek
źródło
użycie mydlanego pliku cookie pomogło mi ominąć problem z uwierzytelnianiem, który miałem w węźle, wielkie dzięki!
nicolasdaudin
5

Użyłem modułu sieci węzła, aby otworzyć gniazdo do usługi sieciowej.

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

Wysyłaj prośby o mydło

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

Przeanalizuj odpowiedź mydła, użyłem modułu - 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();
        }
    }
});

Mam nadzieję, że to komuś pomoże

Vince Lowe
źródło
1
dlaczego miałbyś to zrobić zamiast używać modułu http?
Will Munn,
0

Dodawanie do rozwiązania Kim .J : możesz dodać preserveWhitespace=true, aby uniknąć błędu białych znaków . Lubię to:

soap.CreateClient(url,preserveWhitespace=true,function(...){
J.Aliaga
źródło
0

Możesz również użyć wsdlrdr. EasySoap to po prostu przepisanie wsdlrdr z kilkoma dodatkowymi metodami. Uważaj, ponieważ easysoap nie ma metody getNamespace, która jest dostępna w wsdlrdr.

allen_mxk686
źródło
0

Dla tych, którzy są nowicjuszami SOAPi chcą szybkiego wyjaśnienia i przewodnika, zdecydowanie polecam ten niesamowity artykuł na medium .

Możesz także użyć node-soap pakietu z tym prostym samouczkiem .

MajidJafari
źródło
0

Jeśli potrzebujesz tylko jednorazowej konwersji, https://www.apimatic.io/dashboard?modal=transform pozwala to zrobić, tworząc bezpłatne konto (bez przynależności, po prostu zadziałało).

Jeśli przekształcisz się w Swagger 2.0, możesz utworzyć bibliotekę js z

$ 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
unhammer
źródło