Node.js: วิธีใช้บริการเว็บ SOAP XML


100

ฉันสงสัยว่าอะไรคือวิธีที่ดีที่สุดในการใช้บริการเว็บ SOAP XML กับ node.js

ขอบคุณ!


ในกรณีที่คุณใช้ node-soap และหาวิธีใช้งานได้คุณช่วยสร้าง wsdl ได้ไหม มีเครื่องกำเนิดไฟฟ้าหรือบทช่วยสอนที่ดีในการเขียน wsdl หรือไม่ stackoverflow.com/questions/32480481/…
Andi Giga

ในกรณีที่คุณต้องการตัวอย่างสำหรับการเรียกใช้บริการ. NET WCF ให้ตรวจสอบคำตอบของฉันstackoverflow.com/a/63351804/1370029
Aliaksei Maniuk

คำตอบ:


85

คุณไม่มีตัวเลือกมากมายขนาดนั้น

คุณอาจต้องการใช้หนึ่งใน:


3
ขอบคุณ. มีปัญหากับการติดตั้ง node-soap เนื่องจากการติดตั้ง node-expat ล้มเหลว = (
WHITECOLOR

คุณจะต้องมีส่วนหัวของการพัฒนาชาวต่างชาติเพื่อสร้างมัน
Juicy Scripter

ฉันพบว่ามีการพูดถึงปัญหาเกี่ยวกับส่วนหัว แต่ฉันไม่รู้ว่าฉันควรนำไปรวบรวมไว้ที่ไหนช่วยอธิบายได้ไหม
WHITECOLOR

1
คุณอาจได้รับ 'em ผ่านเครื่องมือการจัดการแพ็คเกจสำหรับระบบปฏิบัติการของคุณ บน Ubuntu เช่นsudo 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) คำขอไปยังบริการเว็บ (โปรดทราบว่ากลไกการสร้างเทมเพลตจาวาสคริปต์มาตรฐานเช่น ejs ( http://embeddedjs.com / ) หรือหนวด ( https://github.com/janl/mustache.js ) สามารถช่วยคุณได้ที่นี่) และสุดท้าย
  • ใช้ตัวแยกวิเคราะห์ XML เพื่อแยกข้อมูลการตอบกลับไปยังอ็อบเจ็กต์ JavaScript

ใช่นี่เป็นแนวทางที่ค่อนข้างสกปรกและมีระดับต่ำ แต่ควรใช้งานได้โดยไม่มีปัญหา


4
น่าเศร้าที่นี่เป็นวิธีที่น่าเชื่อถือที่สุดสำหรับการโต้ตอบกับ SOAP กับ Node.js ฉันยังไม่พบไลบรารีสบู่เดียวที่สามารถส่งคำขอสบู่ได้อย่างถูกต้องใน API จำนวนหนึ่งที่ฉันต้องใช้
AlbertEngelB

1
สกปรก 100% แต่นำฉันไปสู่ผลลัพธ์)))
markkillah

คุณหมายถึงอะไรเมื่อสร้าง input xml` กันแน่?
timaschew

ใช่สามารถยืนยันได้ว่า libs ที่ไม่ได้กล่าวถึงข้างต้นทำงานได้อย่างสมบูรณ์แบบ
someUser

ฉันคิดว่า "Form input xml" หมายถึงการให้ Content-Type เป็น "text / xml"
SSH ใน

23

หาก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 มีโอกาสใดบ้างที่คุณรู้วิธีแก้ไขปัญหานี้
Sujoy

มีปัญหากับ URL ของฉัน ฉันใช้ URL ดั้งเดิมแทนปลายทางที่สร้างโดย SOAPUI ขอบคุณสำหรับรหัสด้านบน
Sujoy

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ไฟล์นี้จะให้อาร์กิวเมนต์สำหรับบริการ soap และเรียก 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 สำหรับการแลกเปลี่ยนข้อมูลซึ่งกำหนดวิธีการเข้าถึงบริการเว็บระยะไกล เรียกไฟล์ wsdl ของคุณbmicalculator.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 (response);" จากไคลเอนต์และ "` "ที่บรรทัดสุดท้ายของไฟล์เซิร์ฟเวอร์
Subhashi

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 โดยใช้สบู่โหนด
Abhishek saini

@Abhisheksaini ตัวอย่างข้างต้นเป็นโพสต์
Halfstop

@ Halfstop กรุณาบอกวิธีรวม SOAPAction ในคำขอ
Sohail

12

ขึ้นอยู่กับจำนวนจุดสิ้นสุดที่คุณต้องการอาจทำได้ง่ายกว่าด้วยตนเอง

ฉันได้ลอง 10 ไลบรารี "soap nodejs" ในที่สุดฉันก็ทำได้ด้วยตนเอง


ฉันลอง node-soap เพื่อเข้าถึงเส้นทาง wsdl แต่มันไม่ได้ผลฉันยังคงได้รับข้อผิดพลาดแม้ว่าสิ่งเดียวกันนี้จะทำงานใน php ได้คุณช่วยตอบคำถามของฉันเกี่ยวกับวิธีที่คุณทำstackoverflow.com/questions/39943122/…
Ammar Ajmal

8

ฉันใช้แพ็กเกจ "สบู่" สำเร็จ ( https://www.npmjs.com/package/soap ) ในการติดตาม WebApis มากกว่า 10 รายการ (Tradetracker, Bbelboon, Affilinet, Webgains, ... )

ปัญหามักมาจากการที่โปรแกรมเมอร์ไม่ได้ตรวจสอบมากนักเกี่ยวกับสิ่งที่ API ระยะไกลต้องการเพื่อเชื่อมต่อหรือพิสูจน์ตัวตน

ตัวอย่างเช่น PHP ส่งคุกกี้ใหม่จากส่วนหัว HTTP โดยอัตโนมัติ แต่เมื่อใช้แพ็คเกจ 'โหนด' จะต้องตั้งค่าอย่างชัดเจน (เช่นแพ็คเกจ 'soap-cookie') ...


การใช้ soap-cookie ช่วยให้ฉันข้ามปัญหาการตรวจสอบสิทธิ์ที่ฉันพบในโหนดได้ขอบคุณมาก!
nicolasdaudin

5

ฉันใช้โมดูลโหนดเน็ตเพื่อเปิดซ็อกเก็ตไปยังบริการเว็บ

/* 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
Will Munn



0

คุณสามารถใช้ wsdlrdr ได้ด้วย EasySoap นั้นเขียนใหม่โดยทั่วไปของ wsdlrdr ด้วยวิธีการพิเศษบางอย่าง ระวังว่า easysoap ไม่มีเมธอด getNamespace ซึ่งมีอยู่ที่ wsdlrdr



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
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.