Node.js: SOAP XML web hizmeti nasıl kullanılır?


99

SOAP XML web hizmetini node.js ile tüketmenin en iyi yolunun ne olduğunu merak ediyorum

Teşekkürler!


Düğüm sabunu kullanırsanız ve nasıl kullanılacağını bulursanız, bir wsdl oluşturmama yardım eder misiniz? Wsdl'nin nasıl yazılacağı konusunda bir jeneratör veya iyi bir öğretici var mı? stackoverflow.com/questions/32480481/…
Andi Giga

NET WCF servis çağrısı için bir örneğe ihtiyacınız olması durumunda, cevabımı kontrol edin stackoverflow.com/a/63351804/1370029
Aliaksei Maniuk

Yanıtlar:


84

O kadar çok seçeneğin yok.

Muhtemelen şunlardan birini kullanmak isteyeceksiniz:


3
Teşekkürler. node-expat yükleme hatası nedeniyle node-soap yüklemesinde sorun
yaşıyor

Bunu oluşturmak için expat geliştirme başlıklarına ihtiyacınız olacak
Juicy Scripter

Başlıklar hakkında söylendiği konuyu buldum, ama nereden almalıyım bilmiyorum, derlemek için nereye koymalıyım, açıklar mısınız lütfen?
WHITECOLOR

1
Muhtemelen işletim sisteminiz için paket yönetim araçları aracılığıyla bunları edinebilirsiniz. Örneğin Ubuntu'dasudo apt-get install libexpat1-dev
Juicy Scripter

1
@RobertBroden, güncelleme için teşekkürler. Lütfen bir dahaki sefere devam edin ve cevabı düzenleyin (veya bir düzenleme önerin)!
Juicy Scripter

31

Sanırım bir alternatif:

  • xml mesajlarının girişini ve çıkışını kaydetmek için SoapUI ( http://www.soapui.org ) gibi bir araç kullanın
  • isteği web hizmetine göndermek (POST) için giriş xml mesajı oluşturmak için düğüm isteği ( https://github.com/mikeal/request ) kullanın (ejs gibi standart javascript şablon oluşturma mekanizmalarının ( http://embeddedjs.com) / ) veya bıyık ( https://github.com/janl/mustache.js ) burada size yardımcı olabilir) ve son olarak
  • JavaScript nesnelerine yanıt verilerinin serisini kaldırmak için bir XML ayrıştırıcı kullanın

Evet, bu oldukça kirli ve düşük seviyeli bir yaklaşım ama sorunsuz çalışmalı


4
Ne yazık ki bu, SOAP ile Node.js ile etkileşim kurmanın en güvenilir yöntemidir. Kullanmak zorunda olduğum bir avuç API için sabun taleplerini düzgün bir şekilde yapan tek bir sabun kitaplığı bulamadım.
AlbertEngelB

1
% 100 kirli, ancak beni sonuçlara getirdi)))
markkillah

xml` girişini tam olarak oluşturmakla ne demek istiyorsunuz?
timaschew

evet, yine de teyit edebilirim, yukarıda bahsedilen kitaplardan hiçbiri mükemmel çalışmıyor.
someUser

Bence "Form girişi xml" yalnızca İçerik Türü "text / xml" vermek anlamına geliyor
SSH Bu

23

İşinize node-soapyaramazsa, node requestmodülü kullanın ve ardından gerekirse xml'yi json'a dönüştürün.

İsteğim çalışmıyordu node-soapve kaynaklarımın ötesinde ücretli desteğin ötesinde bu modül için destek yok. Ben de şunları yaptım:

  1. İndirilen SoapUI benim Linux makine.
  2. WSDL xml'yi yerel bir dosyaya kopyaladı
    curl http://192.168.0.28:10005/MainService/WindowsService?wsdl > wsdl_file.xml
  3. SoapUI'de gittim File > New Soap projectve kendimi yükledim wsdl_file.xml.
  4. Gezginde servislerden birini genişlettim ve isteği sağ tıklayıp tıkladım Show Request Editor.

Oradan bir istek gönderebilir ve çalıştığından emin olabilirim ve ayrıca harici bir istek oluşturmama yardımcı olması için Rawveya HTMLverilerini kullanabilirim .

SoapUI'den isteğim için ham

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)

SoapUI'den 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> 

Aşağıdakileri oluşturmak için yukarıdakileri kullandım 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);

teşekkürler @jtlindsey. Ancak response.statusCode, response.statusMessage olarak 405 yöntemine izin verilmiyor. Şans eseri, bunu nasıl düzelteceğinizi biliyor musunuz?
Sujoy

URL'imle ilgili bir sorun vardı. SOAPUI tarafından oluşturulan uç nokta yerine orijinal URL'yi kullanıyordum. Yukarıdaki kod için teşekkürler.
Sujoy

17

Soap, wsdl ve Node.js kullanmayı başardım. npm install soap

server.jsUzak bir istemci tarafından kullanılacak olan soap hizmetini tanımlayacak bir düğüm sunucusu oluşturun . Bu sabun servisi, ağırlık (kg) ve boy (m) temelinde Vücut Kitle İndeksini hesaplar.

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

Ardından, client.jstarafından tanımlanan sabun hizmetini tüketecek bir dosya oluşturun server.js. Bu dosya, soap servisi için argümanlar sağlayacak ve url'yi SOAP'ın servis portları ve uç noktaları ile arayacaktır.

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 dosyanız, uzak bir web hizmetine nasıl erişileceğini tanımlayan, veri alışverişi için xml tabanlı bir protokoldür. Wsdl dosyanızı arayınbmicalculator.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>

Umarım yardımcı olur


1
Çok teşekkür ederim. Ancak "res.send (response);" öğesini kaldırmak zorunda kaldım. istemciden ve sunucu dosyasının son satırında "" ".
Subhashi

13

Node.js kullanarak bir SOAP hizmetine ham XML göndermenin bulduğum en basit yolu Node.js http uygulamasını kullanmaktır. Şuna benziyor.

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 değişkenini bir dize biçiminde ham xml olarak tanımlardınız.

Ancak, Node.js aracılığıyla bir SOAP hizmetiyle etkileşim kurmak ve ham xml göndermek yerine düzenli SOAP çağrıları yapmak istiyorsanız, Node.js kitaplıklarından birini kullanın. Düğüm sabunu severim .


1
#Halfstop, node-soap kullanarak nasıl POST isteği yapacağımı söyler misin?
Abhishek saini

@Abhisheksaini yukarıdaki örnek bir gönderidir.
Halfstop

@Halfstop Lütfen bana SOAPAction'ı talebe nasıl dahil edeceğimi söyleyin.
Sohail

12

İhtiyacınız olan uç nokta sayısına bağlı olarak, bunu manuel olarak yapmak daha kolay olabilir.

10 kitaplık "soap nodejs" denedim, sonunda elle yapıyorum.


Wsdl yoluna erişmek için node-soap denedim ama çalışmıyor, aynı şey php'de çalışmasına rağmen hata almaya devam ediyorum, stackoverflow.com/questions/39943122/…
Ammar Ajmal

8

"Soap" paketini ( https://www.npmjs.com/package/soap ) 10'dan fazla WebApis'te (Tradetracker, Bbelboon, Affilinet, Webgains, ...) başarıyla kullandım .

Sorunlar genellikle programcıların bağlanmak veya kimlik doğrulamak için hangi uzak API'ye ihtiyaç duyduğu konusunda fazla araştırma yapmamasından kaynaklanır.

Örneğin PHP, tanımlama bilgilerini HTTP üstbilgilerinden otomatik olarak yeniden gönderir, ancak 'düğüm' paketini kullanırken, açıkça ayarlanması gerekir (örneğin 'sabun-çerez' paketi ile) ...


sabun çerezi kullanmak, düğümde yaşadığım bir kimlik doğrulama problemini atlamama yardımcı oldu, çok teşekkürler!
nicolasdaudin


5

Web servisine bir soket açmak için node net modülünü kullandım.

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

Sabun istekleri gönderin

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

Sabun yanıtını ayrıştır, modül kullandım - 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();
        }
    }
});

Umarım birine yardımcı olur


1
http modülünü kullanmak yerine bunu neden yapasınız?
Will Munn

0

Kim .J'nin çözümüne ekleme : preserveWhitespace=trueWhitespace hatasını önlemek için ekleyebilirsiniz . Bunun gibi:

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

0

Wsdlrdr'yi de kullanabilirsiniz. EasySoap, wsdlrdr'nin bazı ekstra yöntemlerle yeniden yazılmasıdır. Easysoap'un wsdlrdr'de bulunan getNamespace yöntemine sahip olmadığına dikkat edin.



0

Tek seferlik bir dönüşüme ihtiyacınız varsa, https://www.apimatic.io/dashboard?modal=transform bunu ücretsiz bir hesap oluşturarak yapmanıza izin verir (bağlantı yok, sadece benim için çalıştı).

Swagger 2.0'a dönüşürseniz, bir js lib yapabilirsiniz.

$ 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
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.