nodejs如何使用soap搭建服务端和客户端

soap概念定义

Simple Object Access Protocol 简单对象访问协议是交换数据的一种协议规范,是一种轻量的、简单的、基于XML(标准通用标记语言下的一个子集)的协议,它被设计成在WEB上交换结构化的和固化的信息。

soap协议定义

相关定义

SOAP封装(envelop),它定义了一个框架,描述消息中的内容是什么,是谁发送的,谁应当接受并处理它以及如何处理它们。
SOAP编码规则(encoding rules),它定义了一种序列化的机制,用于表示应用程序需要使用的数据类型的实例。
SOAPRPC表示(RPC representation),它定义了一个协定,用于表示远程过程调用和应答。
SOAP绑定(binding),它定义了SOAP协议使用哪种协议交换信息,通常使用http。

传输方式

SOAP使用因特网应用层协议作为其传输协议。SMTP以及HTTP协议都可以用来传输SOAP消息,但是由于HTTP在如今的因特网结构中工作得很好,特别是在网络防火墙下仍然工作流畅,所以其更为广泛地被采纳。SOAP亦可以在HTTPS上进行传输。SOAP的消息格式采用xml格式。

wsdl

用来描述如何访问具体的接口,参考网站 https://www.w3.org/TR/wsdl.html http://staff.ustc.edu.cn/~shizhu/DotNet/WSDLxj.htm

nodejs 如何搭建一个soap服务端和客户端

服务端

const fs = require('fs')
const soap = require('soap')
const http = require('http')

// 定义服务
const Service = {
  Service_one: {
    // 定义接口
    TestPort: {
      func_1: function (args) {
        console.log('func_1', args);
        return {
          name: args.name
        };
      },

      func_2: function (args, callback) {
        console.log('func_2', args);

        callback({
          name: args.name
        })
      },

      func_3: function (args) {
        console.log('func_3', args);
        return new Promise((resolve) => {
          resolve({
            name: args.name,
            async: true
          })
        });
      },
      
      func_4: function (args, cb, headers, req) {
        console.log('func_4', args);
        console.log(headers);
        console.log('SOAP `reallyDetailedFunction` request from ' + req.connection.remoteAddress);
        return {
          name: headers.Token
        };
      }
    }
  }
};
const xml = fs.readFileSync('./index_2.wsdl', 'utf8');

// 创建一个http服务
const server = http.createServer(function (request, response) {
  response.end('404: Not Found: ' + request.url);
});
server.listen(8000);


// // 基于上述的http服务创建一个webservice
const soapServer = soap.listen(server, '/wsdl', Service, xml, function () {
  console.log('server initialized');
});

soapServer.addSoapHeader(function(methodName, args, headers, req) {
  console.log('Adding headers for method', methodName);
  return {
    MyHeader1: 'test1',
    MyHeader2: headers.Token
  };
  // or you can return "SomeValue"
});

使用到的wsdl文件



<wsdl:definitions name="StockQuote" targetNamespace="http://example.com/stockquote.wsdl"
  xmlns:tns="http://example.com/stockquote.wsdl" xmlns:xsd1="http://example.com/stockquote.xsd"
  xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">
  
  <wsdl:types>
    <xsd:schema targetNamespace="http://example.com/stockquote.xsd"
      xmlns:xsd="http://www.w3.org/2000/10/XMLSchema">
      <xsd:element name="funcRequest">
        <xsd:complexType>
          <xsd:all>
            
            <xsd:element name="name" type="xsd:string" />
            <xsd:element name="age" type="xsd:interge" />
          xsd:all>
        xsd:complexType>
      xsd:element>
      <xsd:element name="funcResponse">
        <xsd:complexType>
          <xsd:all>
            <xsd:element name="name" type="xsd:string" />
          xsd:all>
        xsd:complexType>
      xsd:element>
      <xsd:element name="funcAsyncResponse">
        <xsd:complexType>
          <xsd:all>
            <xsd:element name="name" type="xsd:object" />
          xsd:all>
        xsd:complexType>
      xsd:element>
    xsd:schema>
  wsdl:types>

  
  <wsdl:message name="FuncInput">
    <wsdl:part name="body" element="xsd1:funcRequest" />
  wsdl:message>
  <wsdl:message name="FuncOutput">
    <wsdl:part name="body" element="xsd1:funcResponse" />
  wsdl:message>
  <wsdl:message name="funcAsyncOutput">
    <wsdl:part name="body" element="xsd1:funcAsyncResponse" />
  wsdl:message>

  
  <wsdl:portType name="TestPortType">
    <wsdl:operation name="func_1">
      <wsdl:input message="tns:FuncInput" />
      <wsdl:output message="tns:FuncOutput" />
    wsdl:operation>
    <wsdl:operation name="func_2">
      <wsdl:input message="tns:FuncInput" />
      <wsdl:output message="tns:FuncOutput" />
    wsdl:operation>
    <wsdl:operation name="func_3">
      <wsdl:input message="tns:FuncInput" />
      <wsdl:output message="tns:FuncOutput" />
    wsdl:operation>
    <wsdl:operation name="func_4">
      <wsdl:input message="tns:FuncInput" />
      <wsdl:output message="tns:FuncOutput" />
    wsdl:operation>
  wsdl:portType>

  
  <wsdl:binding name="TestBinding" type="tns:TestPortType">
    <soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http" />
    
    <wsdl:operation name="func_1">
      <soap:operation soapAction="http://localhost:8000/func_1" />
      <wsdl:input>
        <soap:body use="literal" />
      wsdl:input>
      <wsdl:output>
        <soap:body use="literal" />
      wsdl:output>
    wsdl:operation>
    <wsdl:operation name="func_2">
      <soap:operation soapAction="http://localhost:8000/func_2" />
      <wsdl:input>
        <soap:body use="literal" />
      wsdl:input>
      <wsdl:output>
        <soap:body use="literal" />
      wsdl:output>
    wsdl:operation>
    <wsdl:operation name="func_3">
      <soap:operation soapAction="http://localhost:8000/func_3" />
      <wsdl:input>
        <soap:body use="literal" />
      wsdl:input>
      <wsdl:output>
        <soap:body use="literal" />
      wsdl:output>
    wsdl:operation>
    <wsdl:operation name="func_4">
      <soap:operation soapAction="http://localhost:8000/func_4" />
      <wsdl:input>
        <soap:body use="literal" />
      wsdl:input>
      <wsdl:output>
        <soap:body use="literal" />
      wsdl:output>
    wsdl:operation>
  wsdl:binding>

  
  <wsdl:service name="Service_one">
    <wsdl:port name="TestPort" binding="tns:TestBinding">
      <soap:address location="http://localhost:8000/wsdl" />
    wsdl:port>
  wsdl:service>
wsdl:definitions>

客户端使用

const soap = require("soap");
var url = 'http://localhost:8000/wsdl?wsdl';
function cb (err, res) {
  console.log('cb', res);
}

async function main () {
  const client = await soap.createClientAsync(url)
    .catch(e => console.log(e))

  // 请求头设置参数
  client.addSoapHeader({Token: 'test'})

  // 作为 JavaScript 对象的服务、端口和方法的描述
  console.log(client.describe());


  client.func_1({ name: 'test' }, cb)

  /**
   * result是一个数组,分别是 返回结果、 返回xml字符串、返回表头、请求xml字符串 
   * result is a javascript array containing result, rawResponse, soapheader, and rawRequest  --返回一个js对象
     result is a javascript object
     rawResponse is the raw xml response string
     soapHeader is the response soap header as a javascript object
     rawRequest is the raw xml request string
   * 
   */
  const res_2 = await client.func_2Async({ name: 'test' })
    .catch(e=>console.log(e))
  console.log('res_2', res_2 && res_2[0]);

  const res_3 = await client.func_3Async({ name: 'test' })
    .catch(e=>console.log(e))
  console.log(res_3.length, res_3);
  console.log('res_3', res_3 && res_3[0]);
  

  client.func_4({ name: 'test' }, cb, { Headers: { Token: 'test' } })
}

main()

你可能感兴趣的:(node.js)