Node.js:如何使用SOAP XML Web服务

时间:2011-12-28 11:22:16

标签: xml node.js soap

我想知道使用node.js

使用SOAP XML Web服务的最佳方法是什么

谢谢!

14 个答案:

答案 0 :(得分:75)

你没有那么多选择。

你可能想要使用以下之一:

答案 1 :(得分:30)

我认为另一种选择是:

  • 使用SoapUI(http://www.soapui.org)等工具记录输入和输出xml消息
  • 使用节点请求(https://github.com/mikeal/request)形成输入xml消息以将请求发送(POST)到Web服务(请注意标准javascript模板机制,如ejs(http://embeddedjs.com/)或小胡子({ {3}})可以帮助你)最后
  • 使用XML解析器将响应数据反序列化为JavaScript对象

是的,这是一个相当肮脏和低级别的方法,但它应该没有问题

答案 2 :(得分:15)

如果node-soap不适合您,只需使用node request模块,然后根据需要将xml转换为json。

我的请求并未与node-soap合作,并且除了付费支持之外,没有对该模块的支持,这超出了我的资源范围。所以我做了以下事情:

  1. 在我的Linux机器上下载了SoapUI
  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
  5. 从那里我可以发送请求并确保它有效,我也可以使用RawHTML数据来帮助我构建外部请求。

    来自SoapUI的Raw我的请求

    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的

    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> 
    

    我使用上述内容构建了以下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);
    

答案 3 :(得分:14)

我发现使用Node.js将原始XML发送到SOAP服务的最简单方法是使用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。

但是,如果您只想通过Node.js与SOAP服务进行交互并进行常规SOAP调用,而不是发送原始xml,请使用其中一个Node.js库。我喜欢node-soap

答案 4 :(得分:13)

我设法使用soap,wsdl和Node.js 您需要使用npm install soap

安装soap

创建一个名为server.js的节点服务器,该服务器将定义远程客户端要使用的soap服务。该肥皂服务根据体重(kg)和身高(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);

接下来,创建一个client.js文件,该文件将使用server.js定义的soap服务。该文件将为soap服务提供参数,并使用SOAP的服务端口和端点调用url。

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的数据交换协议,用于定义如何访问远程Web服务。请调用您的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>

希望有所帮助

答案 5 :(得分:9)

根据您需要的端点数量,可能更容易手动执行。

我已经尝试了10个库“soap nodejs”我终于手动完成了。

答案 6 :(得分:8)

我在10多个跟踪WebApis(Tradetracker,Bbelboon,Affilinet,Webgains,...)上成功使用了“soap”包(https://www.npmjs.com/package/soap)。

问题通常来自这样一个事实,即程序员不会对远程API需要进行多少调查才能进行连接或验证。

例如PHP自动从HTTP头重新发送cookie,但是当使用'node'包时,必须明确设置(例如'soap-cookie'包)...

答案 7 :(得分:5)

答案 8 :(得分:5)

我使用节点网络模块打开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);          
    }
});

发送肥皂请求

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

希望它有助于某人

答案 9 :(得分:0)

添加到Kim .J's solution:您可以添加preserveWhitespace=true以避免出现空白错误。像这样:

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

答案 10 :(得分:0)

您也可以使用wsdlrdr。 EasySoap基本上是使用一些其他方法重写wsdlrdr的。 请注意,easysoap没有wsdlrdr可用的getNamespace方法。

答案 11 :(得分:0)

对于那些刚接触SOAP并想要快速解释和指导的人,我强烈建议您使用这种很棒的媒介article

您还可以通过简单的package使用node-soap tutorial

答案 12 :(得分:0)

如果您只需要一次转换,https://www.apimatic.io/dashboard?modal=transform允许您通过建立一个免费帐户来实现此目的(无从属关系,对我来说才有用)。

如果您要转换为Swagger 2.0,则可以使用以下方式创建js库

<form action="phph.php">
    <input type="date" name="date" pattern="(06){1}[- /.](30){1}[- /.](1989){1}">
    <button>submit</button>
</form>

答案 13 :(得分:0)

在我看来,避免使用 nodejs 查询 SOAP API。

两种选择:

  1. 如果您是 SOAP API 的所有者,请让它处理 xml 和 json 请求,因为 javascript 可以很好地处理 json。

  2. 在 php 中实现一个 API 网关(因为 php 可以很好地处理 SOAP)。网关会以 json 格式接收您的输入,然后查询 xml 中的 SOAP API 并将 xml 响应转换为 json。