Simple Object Access Protocol 简单对象访问协议是交换数据的一种协议规范,是一种轻量的、简单的、基于XML(标准通用标记语言下的一个子集)的协议,它被设计成在WEB上交换结构化的和固化的信息。
SOAP封装(envelop),它定义了一个框架,描述消息中的内容是什么,是谁发送的,谁应当接受并处理它以及如何处理它们。
SOAP编码规则(encoding rules),它定义了一种序列化的机制,用于表示应用程序需要使用的数据类型的实例。
SOAPRPC表示(RPC representation),它定义了一个协定,用于表示远程过程调用和应答。
SOAP绑定(binding),它定义了SOAP协议使用哪种协议交换信息,通常使用http。
SOAP使用因特网应用层协议作为其传输协议。SMTP以及HTTP协议都可以用来传输SOAP消息,但是由于HTTP在如今的因特网结构中工作得很好,特别是在网络防火墙下仍然工作流畅,所以其更为广泛地被采纳。SOAP亦可以在HTTPS上进行传输。SOAP的消息格式采用xml格式。
用来描述如何访问具体的接口,参考网站 https://www.w3.org/TR/wsdl.html http://staff.ustc.edu.cn/~shizhu/DotNet/WSDLxj.htm
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: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()