Wcf.js:从 Node.js 调用 WCF Web 服务





5.00/5 (2投票s)
从 Node 应用程序中调用现有 Web 服务。
引言
Node.js 正成为初创公司和企业开发者的绝佳选择。虽然 REST Web 服务是新的 Node 开发的首选,但也需要从 Node 应用程序中调用现有 Web 服务。在调用 WCF Web 服务时,这是一个挑战,因为 WCF 支持许多不容易生成的标准和协议。Wcf.js 是一个 Node.js 库,旨在简化此方案。
背景
你可能要问的第一个问题是,为什么我们需要一个特殊的库来调用 SOAP Web 服务。毕竟,HTTP 在 Node.js 中是一流公民,我们可以简单地通过 HTTP 将 SOAP 发送到服务。但是,Web 服务可能支持诸如 Ws-Security 或 MTOM 之类的标准,而 Node 无法开箱即用地支持这些标准。实际上,这正是另一个项目 ws.js 解决的问题。
这两个项目是互补的。虽然 wcf.js 没有在 ws.js 之上添加任何新的标准实现,但它模仿了 WCF API。这意味着用户可以使用其原生 API 访问 WCF,而无需学习新的范例。所有这些都是以纯 JavaScript 方式完成的!
使用代码
1. 首先,你必须安装 Wcf.js 模块
npm install wcf.js
2. 现在编写你的代码:
var BasicHttpBinding = require('wcf.js').BasicHttpBinding
, Proxy = require('wcf.js').Proxy
, binding = new BasicHttpBinding(
{ SecurityMode: "TransportWithMessageCredential"
, MessageClientCredentialType: "UserName"
})
, proxy = new Proxy(binding, "https://:7171/Service/clearUsername")
, message = "<Envelope xmlns='http://schemas.xmlsoap.org/soap/envelope/'>" +
"<Header />" +
"<Body>" +
"<GetData xmlns='http://tempuri.org/'>" +
"<value>123</value>" +
"</GetData>" +
"</Body>" +
"</Envelope>"
proxy.ClientCredentials.Username.Username = "yaron"
proxy.ClientCredentials.Username.Password = "1234"
proxy.send(message, "http://tempuri.org/IService/GetData", function(response, ctx) {
console.log(response)
});
如果这段代码看起来很熟悉,那么你是对的 - 它与 WCF API 相同。因此,你可以像使用 WCF 一样自由地创建绑定和行为。上面的例子在这行中初始化了一个 wcf basicHttpBinding:
binding = new BasicHttpBinding(
{ SecurityMode: "TransportWithMessageCredential"
, MessageClientCredentialType: "UserName"
})
然后它配置凭据
proxy.ClientCredentials.Username.Username = "yaron"
proxy.ClientCredentials.Username.Password = "1234"
然后调用服务
proxy.send(message, "http://tempuri.org/IService/GetData", function(response, ctx) {
...
});
与 WCF 完全一样!
自定义绑定示例
相同的方法可以帮助我们构建自定义绑定:
var CustomBinding = require('wcf.js').CustomBinding
, MtomMessageEncodingBindingElement = require('wcf.js').MtomMessageEncodingBindingElement
, HttpTransportBindingElement = require('wcf.js').HttpTransportBindingElement
, Proxy = require('wcf.js').Proxy
, fs = require('fs')
, binding = new CustomBinding(
[ new MtomMessageEncodingBindingElement({MessageVersion: "Soap12WSAddressing10"}),
, new HttpTransportBindingElement()
])
, proxy = new Proxy(binding, "https://:7171/Service/mtom")
, message = '<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope">' +
'<s:Header />' +
'<s:Body>' +
'<EchoFiles xmlns="http://tempuri.org/">' +
'<value xmlns:a="http://schemas.datacontract.org/2004/07/" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">' +
'<a:File1 />' +
'</value>' +
'</EchoFiles>' +
'</s:Body>' +
'</s:Envelope>'
proxy.addAttachment("//*[local-name(.)='File1']", "me.jpg");
proxy.send(message, "http://tempuri.org/IService/EchoFiles", function(response, ctx) {
var file = proxy.getAttachment("//*[local-name(.)='File1']")
fs.writeFileSync("result.jpg", file)
});
你应该注意这里如何在自定义绑定上定义通道
binding = new CustomBinding(
[ new MtomMessageEncodingBindingElement({MessageVersion: "Soap12WSAddressing10"}),
, new HttpTransportBindingElement()
])
你可以创建自己的通道并将它们放在管道中。这个具体例子使用了 mtom 通道。
为什么 MTOM 需要额外的工作?
上面的例子使用了 MTOM 通道。这就是为什么我们需要通过指定 base64 元素路径来做更多的工作:
proxy.addAttachment("//*[local-name(.)='File1']", "me.jpg");
我们不需要在 WCF 中这样做,那么为什么 Wcf.js 需要这样做?
让我们看看这个 soap 元素:
<a:File1 />
如果未使用 MTOM,那么这部分将填充 me.jpg 的 base64 表示形式
<a:File1>PS2Kqw23A2A98...</a:File1>
我们需要告诉 MTOM 通道获取此内容并将其作为二进制有效负载放在消息之外。那么为什么 WCF 不需要我们告诉它这些信息呢? WCF 是一个完整的 soap 堆栈,它也基于 WSDL 生成代理。当 WCF 生成 File1 参数时,它将其标记为 MTOM 转换的候选对象。因此,Wcf 从 Wsdl 获取了此信息。由于 Wcf.js 是一个纯 ws-* 堆栈(而不是 soap 堆栈),因此它无法访问 wsdl,我们需要提供此信息。
支持的绑定
Wcf.js 目前支持一个子集
- BasicHttpBinding
- WSHttpBinding
- CustomBinding
当前的子集包括
- MTOM / 文本编码
- WS-Addressing(所有版本)
- 传输安全(SSL)
- 带有消息凭据(用户名)的传输
Ws.js 的未来
Wcf.js 是 Node.js 的 WCF 的纯 JavaScript 实现。
Wcf.js 是一个不断发展的框架。对于未来版本,我计划添加更多绑定支持,如 net.tcp 和 WsHttpBinding 中的专有安全协商。如果你有任何特殊要求,请从我的博客发送电子邮件给我。如果你想提供帮助,请随意在 github 上 fork Wcf.js - 这是发展 Wcf.js 的最快方式。
更多信息
查看项目 github 页面
查看我的博客
从我的博客给我发电子邮件