Node.js: come utilizzare il servizio Web XML SOAP


99

Mi chiedo quale sia il modo migliore per utilizzare il servizio web XML SOAP con node.js

Grazie!


Nel caso in cui utilizzi node-soap e hai capito come usarlo, potresti aiutarmi a creare un file wsdl. Esiste un generatore o un buon tutorial su come scrivere il file wsdl. stackoverflow.com/questions/32480481/…
Andi Giga

Nel caso abbiate bisogno di un esempio per chiamata di servizio NET WCF, controllare la mia risposta stackoverflow.com/a/63351804/1370029
Aliaksei Maniuk

Risposte:


83

Non hai molte opzioni.

Probabilmente vorrai usare uno di:


3
Grazie. avere problemi con l'installazione di node-soap a causa di un errore di installazione di node-expat = (
WHITECOLOR

Avrai bisogno di intestazioni di sviluppo per espatriati per costruirlo
Juicy Scripter

Ho scoperto che il problema è stato detto sulle intestazioni, ma non so dove dovrei trovarlo dove dovrei metterlo per compilare, potresti spiegare, per favore?
WHITECOLOR

1
Probabilmente puoi ottenerli tramite gli strumenti di gestione dei pacchetti per il tuo sistema operativo. Su Ubuntu, ad esempiosudo apt-get install libexpat1-dev
Juicy Scripter

1
@RobertBroden, grazie per l'aggiornamento. La prossima volta vai avanti e modifica la risposta (o suggerisci una modifica)!
Juicy Scripter

31

Penso che un'alternativa sarebbe:

Sì, questo è un approccio piuttosto sporco e di basso livello, ma dovrebbe funzionare senza problemi


4
Purtroppo, questo è il metodo più affidabile per interagire con SOAP con Node.js. Devo ancora trovare una singola libreria soap che effettui correttamente le richieste soap sulla manciata di API che devo usare.
AlbertEngelB

1
100% sporco, ma mi ha portato ai risultati)))
markkillah

cosa intendete tutti con per formare esattamente l'input xml`?
timaschew

sì, posso confermare ancora, nessuna delle librerie sopra menzionate funziona perfettamente.
qualche utente il

Penso che "Form input xml" significhi semplicemente fornire un Content-Type "text / xml"
SSH questo

22

Se node-soapnon funziona per te, usa il node requestmodulo e quindi converti l'xml in json se necessario.

La mia richiesta non funzionava node-soape non c'è supporto per quel modulo oltre al supporto a pagamento, che era oltre le mie risorse. Quindi ho fatto quanto segue:

  1. scaricato ho SoapUI sulla mia macchina Linux.
  2. ha copiato l'xml WSDL in un file locale
    curl http://192.168.0.28:10005/MainService/WindowsService?wsdl > wsdl_file.xml
  3. In SoapUI sono andato a File > New Soap project e ho caricato il mio file wsdl_file.xml.
  4. Nel navigatore ho espanso uno dei servizi, ho cliccato con il tasto destro sulla richiesta e poi cliccato Show Request Editor .

Da lì potevo inviare una richiesta e assicurarmi che funzionasse e potevo anche usare il RawHTML dati o per aiutarmi a creare una richiesta esterna.

Raw da SoapUI per la mia richiesta

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

Ho usato quanto sopra per creare quanto segue 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);

grazie @jtlindsey. Ma sto ottenendo il metodo 405 non consentito come response.statusCode, response.statusMessage. Per caso sai come risolvere questo problema?
Sujoy

Si è verificato un problema con il mio URL. Stavo usando l'URL originale invece dell'endpoint generato da SOAPUI. Grazie per il codice sopra.
Sujoy

17

Sono riuscito a usare soap, wsdl e Node.js È necessario installare soap con npm install soap

Creare un server nodo chiamato server.jsche definirà il servizio soap da utilizzare da un client remoto. Questo servizio di sapone calcola l'indice di massa corporea in base al peso (kg) e all'altezza (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);

Successivamente, crea un client.jsfile che utilizzerà il servizio soap definito da server.js. Questo file fornirà argomenti per il servizio soap e chiamerà l'URL con le porte e gli endpoint del servizio 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);
      }
    });
  }
});

Il file wsdl è un protocollo basato su xml per lo scambio di dati che definisce come accedere a un servizio Web remoto. Chiama il tuo file 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>

Spero che sia d'aiuto


1
Grazie mille. Tuttavia, ho dovuto rimuovere "res.send (response);" dal client e "` "nell'ultima riga del file del server.
Subhashi

13

Il modo più semplice che ho trovato per inviare semplicemente XML non elaborato a un servizio SOAP utilizzando Node.js è utilizzare l'implementazione http di Node.js. Sembra questo.

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

Avresti definito la variabile xml come XML grezzo sotto forma di stringa.

Ma se vuoi solo interagire con un servizio SOAP tramite Node.js ed effettuare chiamate SOAP regolari, invece di inviare XML non elaborato, usa una delle librerie Node.js. Mi piace il sapone ai nodi .


1
#Halfstop, potresti dirmi come fare una richiesta POST usando node-soap?
Abhishek saini

@ Abhisheksaini l'esempio sopra è un post.
Halfstop

@Halfstop Dimmi gentilmente come includere SOAPAction nella richiesta.
Sohail

12

A seconda del numero di endpoint necessari, potrebbe essere più semplice farlo manualmente.

Ho provato 10 librerie "soap nodejs" finalmente lo faccio manualmente.


Ho provato node-soap per accedere alla route wsdl ma non funziona, continuo a ricevere errori anche se la stessa cosa funziona in php Puoi rispondere alla mia domanda su come hai fatto stackoverflow.com/questions/39943122/…
Ammar Ajmal

8

Ho utilizzato con successo il pacchetto "soap" ( https://www.npmjs.com/package/soap ) su più di 10 WebApis di monitoraggio (Tradetracker, Bbelboon, Affilinet, Webgains, ...).

I problemi di solito derivano dal fatto che i programmatori non indagano molto su ciò di cui l'API remota ha bisogno per connettersi o autenticarsi.

Ad esempio PHP reinvia automaticamente i cookie dalle intestazioni HTTP, ma quando si utilizza il pacchetto 'node', deve essere impostato esplicitamente (ad esempio dal pacchetto 'soap-cookie') ...


l'utilizzo di soap-cookie mi ha aiutato a bypassare un problema di autenticazione che stavo avendo nel nodo, grazie mille!
nicolasdaudin


5

Ho usato il modulo node net per aprire un socket al 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);          
    }
});

Invia richieste di sapone

/* 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, ho usato il modulo - 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();
        }
    }
});

Spero che aiuti qualcuno


1
perché dovresti farlo invece di usare il modulo http?
Will Munn

0

In aggiunta alla soluzione di Kim .J : puoi aggiungere preserveWhitespace=trueper evitare un errore di spazio vuoto . Come questo:

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

0

Puoi anche usare wsdlrdr. EasySoap è fondamentalmente riscrittura di wsdlrdr con alcuni metodi extra. Fai attenzione che easysoap non disponga del metodo getNamespace disponibile su wsdlrdr.


0

Per coloro che sono nuovi SOAPe desiderano una rapida spiegazione e guida, consiglio vivamente questo fantastico articolo medio .

Puoi anche usare il node-soap pacchetto , con questo semplice tutorial .


0

Se hai solo bisogno di una conversione una tantum, https://www.apimatic.io/dashboard?modal=transform ti consente di farlo creando un account gratuito (nessuna affiliazione, ha funzionato solo per me).

Se ti trasformi in Swagger 2.0, puoi creare una libreria js con

$ 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
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.