Node.js: cách sử dụng dịch vụ web SOAP XML


99

Tôi tự hỏi đâu là cách tốt nhất để sử dụng dịch vụ web SOAP XML với node.js

Cảm ơn!


Trong trường hợp bạn sử dụng node-soap và đã tìm ra cách sử dụng nó, bạn có thể giúp tôi tạo một wsdl. Có một trình tạo hoặc một hướng dẫn tốt về cách viết wsdl. stackoverflow.com/questions/32480481/…
Andi Giga

Trong trường hợp bạn cần một ví dụ cho cuộc gọi dịch vụ .NET WCF, hãy kiểm tra câu trả lời của tôi stackoverflow.com/a/63351804/1370029
Aliaksei Maniuk

Câu trả lời:


83

Bạn không có nhiều lựa chọn.

Có thể bạn sẽ muốn sử dụng một trong số:


3
Cảm ơn. gặp vấn đề với nút-xà phòng cài đặt vì lỗi cài đặt nút-người nước ngoài = (
WHITECOLOR

Bạn sẽ cần các tiêu đề phát triển của người nước ngoài để xây dựng nó
Juicy Scripter

Tôi tìm thấy vấn đề được nói về tiêu đề, nhưng tôi không biết tôi nên lấy nó ở đâu, tôi nên đặt nó ở đâu để biên dịch, bạn có thể giải thích không?
WHITECOLOR

1
Có lẽ bạn có thể tải chúng qua các công cụ quản lý gói cho hệ điều hành của mình. Ví dụ trên Ubuntusudo apt-get install libexpat1-dev
Juicy Scripter

1
@RobertBroden, cảm ơn bạn đã cập nhật. Lần sau vui lòng tiếp tục và chỉnh sửa câu trả lời (hoặc đề xuất chỉnh sửa)!
Juicy Scripter

31

Tôi nghĩ rằng một giải pháp thay thế sẽ là:

  • sử dụng một công cụ như SoapUI ( http://www.soapui.org ) để ghi lại các thông báo xml đầu vào và đầu ra
  • sử dụng yêu cầu nút ( https://github.com/mikeal/request ) để tạo thông báo xml đầu vào để gửi (ĐĂNG) yêu cầu tới dịch vụ web (lưu ý rằng các cơ chế tạo mẫu javascript tiêu chuẩn như ejs ( http://embeddedjs.com) / ) hoặc ria mép ( https://github.com/janl/mustache.js ) có thể giúp bạn ở đây) và cuối cùng
  • sử dụng trình phân tích cú pháp XML để giải mã dữ liệu phản hồi cho các đối tượng JavaScript

Có, đây là một cách tiếp cận khá bẩn và cấp thấp nhưng nó sẽ hoạt động mà không có vấn đề gì


4
Đáng buồn thay, đây là phương pháp đáng tin cậy nhất để tương tác với SOAP với Node.js. Tôi vẫn chưa tìm thấy một thư viện xà phòng nào thực hiện đúng các yêu cầu xà phòng trên một số API mà tôi phải sử dụng.
AlbertEngelB

1
100% bẩn, nhưng đã đưa tôi đến kết quả)))
markkillah

ý của bạn là gì để tạo thành xml` đầu vào chính xác?
timaschew

vâng, vẫn có thể khẳng định, không phải các lib đã đề cập ở trên hoạt động hoàn hảo.
someUser,

Tôi nghĩ rằng "Xml đầu vào biểu mẫu" có nghĩa là chỉ cung cấp Loại nội dung là "text / xml"
SSH Này

22

Nếu node-soapkhông hiệu quả với bạn, chỉ cần sử dụng node requestmô-đun và sau đó chuyển đổi xml thành json nếu cần.

Yêu cầu của tôi không hoạt động node-soapvà không có hỗ trợ nào cho mô-đun đó ngoài hỗ trợ trả phí, vượt quá tài nguyên của tôi. Vì vậy, tôi đã làm như sau:

  1. đã tải xuống SoapUI trên máy Linux của tôi.
  2. đã sao chép xml WSDL vào một tệp cục bộ
    curl http://192.168.0.28:10005/MainService/WindowsService?wsdl > wsdl_file.xml
  3. Trong SoapUI, tôi đã truy cập File > New Soap projectvà tải lên của mình wsdl_file.xml.
  4. Trong trình điều hướng, tôi đã mở rộng một trong các dịch vụ và nhấp chuột phải vào yêu cầu và nhấp vào Show Request Editor.

Từ đó, tôi có thể gửi một yêu cầu và đảm bảo rằng nó hoạt động và tôi cũng có thể sử dụng Rawhoặc HTMLdữ liệu để giúp tôi xây dựng một yêu cầu bên ngoài.

Nguyên từ SoapUI cho yêu cầu của tôi

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 từ 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> 

Tôi đã sử dụng phần trên để xây dựng phần sau 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);

cảm ơn @jtlindsey. Nhưng tôi đang nhận được phương thức 405 không được phép là response.statusCode, response.statusMessage. Bạn có biết cách sửa lỗi này không?
Sujoy

Có vấn đề với URL của tôi. Tôi đang sử dụng URL gốc thay vì điểm cuối được tạo bởi SOAPUI. Cảm ơn vì mã trên.
Sujoy

17

Tôi đã quản lý để sử dụng xà phòng, wsdl và Node.js Bạn cần cài đặt xà phòng với npm install soap

Tạo một máy chủ nút có tên server.jssẽ xác định dịch vụ xà phòng sẽ được sử dụng bởi một máy khách từ xa. Dịch vụ xà phòng này tính Chỉ số khối cơ thể dựa trên cân nặng (kg) và chiều cao (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);

Tiếp theo, tạo một client.jstệp sẽ sử dụng dịch vụ xà phòng được xác định bởi server.js. Tệp này sẽ cung cấp các đối số cho dịch vụ xà phòng và gọi url với các cổng dịch vụ và điểm cuối của 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);
      }
    });
  }
});

Tệp wsdl của bạn là một giao thức dựa trên xml để trao đổi dữ liệu xác định cách truy cập dịch vụ web từ xa. Gọi tệp wsdl của bạ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>

Hy vọng nó giúp


1
Cảm ơn bạn rất nhiều. Tuy nhiên, tôi đã phải xóa "res.send (response);" từ máy khách và "` "ở dòng cuối cùng của tệp máy chủ.
Subhashi

13

Cách đơn giản nhất mà tôi tìm thấy để chỉ gửi XML thô đến dịch vụ SOAP bằng Node.js là sử dụng triển khai http Node.js. Nó trông như thế này.

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

Bạn đã định nghĩa biến xml là xml thô ở dạng một chuỗi.

Nhưng nếu bạn chỉ muốn tương tác với một dịch vụ SOAP qua Node.js và thực hiện các cuộc gọi SOAP thông thường, thay vì gửi xml thô, hãy sử dụng một trong các thư viện Node.js. Tôi thích xà phòng nút .


1
#Halfstop, bạn có thể vui lòng cho tôi biết cách thực hiện yêu cầu ĐĂNG bằng cách sử dụng node-soap không?
Abhishek saini

@Abhisheksaini ví dụ trên là một bài đăng.
Hiệp

@Halfstop Vui lòng cho tôi biết cách đưa SOAPAction vào yêu cầu.
Sohail

12

Tùy thuộc vào số lượng điểm cuối bạn cần, có thể dễ dàng hơn để làm điều đó theo cách thủ công.

Tôi đã thử 10 thư viện "soap nodejs". Cuối cùng thì tôi cũng làm được theo cách thủ công.


Tôi đã thử node-soap để truy cập tuyến đường wsdl nhưng nó không hoạt động, tôi tiếp tục gặp lỗi mặc dù điều tương tự hoạt động trong php Bạn có thể trả lời câu hỏi của tôi về cách bạn đã làm nó stackoverflow.com/questions/39943122/…
Ammar Ajmal

8

Tôi đã sử dụng thành công gói "xà phòng" ( https://www.npmjs.com/package/soap ) trên hơn 10 WebApis theo dõi (Tradetracker, Bbelboon, Affilinet, Webgains, ...).

Các vấn đề thường đến từ thực tế là các lập trình viên không điều tra nhiều về những gì API từ xa cần để kết nối hoặc xác thực.

Ví dụ: PHP tự động gửi lại cookie từ các tiêu đề HTTP, nhưng khi sử dụng gói 'nút', nó phải được đặt rõ ràng (ví dụ: bằng gói 'soap-cookie') ...


sử dụng soap-cookie đã giúp tôi vượt qua sự cố xác thực mà tôi gặp phải trong nút, cảm ơn rất nhiều!
nicolasdaudin


5

Tôi đã sử dụng mô-đun node net để mở một ổ cắm cho dịch vụ web.

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

Gửi yêu cầu xà phòng

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

Phân tích cú pháp xà phòng phản hồi, tôi đã sử dụng mô-đun - 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();
        }
    }
});

Hy vọng nó sẽ giúp ai đó


1
tại sao bạn làm điều này thay vì sử dụng mô-đun http?
Will Munn

0

Thêm vào giải pháp của Kim .J : bạn có thể thêm preserveWhitespace=trueđể tránh lỗi Khoảng trắng. Như thế này:

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

0

Bạn cũng có thể sử dụng wsdlrdr. EasySoap về cơ bản là viết lại wsdlrdr với một số phương thức bổ sung. Hãy cẩn thận rằng easysoap không có phương thức getNamespace có sẵn tại wsdlrdr.


0

Đối với những người mới sử dụng SOAPvà muốn được giải thích và hướng dẫn nhanh, tôi thực sự khuyên bạn nên sử dụng bài viết phương tiện tuyệt vời này .

Bạn cũng có thể sử dụng node-soap gói , với hướng dẫn đơn giản này .


0

Nếu bạn chỉ cần chuyển đổi một lần, https://www.apimatic.io/dashboard?modal=transform cho phép bạn thực hiện việc này bằng cách tạo một tài khoản miễn phí (không có liên kết, nó chỉ hoạt động với tôi).

Nếu bạn biến thành Swagger 2.0, bạn có thể tạo js lib với

$ 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
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.