65.9K
CodeProject 正在变化。 阅读更多。
Home

Ws.js: 一个用于 Node.js 的 Ws-* 实现

starIconstarIconstarIconstarIconstarIcon

5.00/5 (1投票)

2012 年 4 月 26 日

CPOL

3分钟阅读

viewsIcon

36963

Ws.js 是一个 Node.js 模块,允许使用 soap web 服务,这些服务利用 ws-* 标准(ws-security, mtom 等)。

介绍 

Node.js 是编写可扩展服务器应用程序的绝佳平台。 其中一些应用程序需要与现有的 Web 服务通信。 只要这些服务是基于 Rest 的,这就不是问题 - Rest 服务在 node 中是一等公民。 如果我们需要使用 soap web 服务,我们可以快速搜索一下以找到 node-soap,或者我们可以决定自己手工构建 soap 信封。 真正的挑战是当 node 需要使用利用 WS-* 标准(WS-Security、MTOM 等)的 soap 服务时。 几个月前,当我遇到这种情况时,我找不到任何模块可以提供帮助。 这就是我决定构建 Ws.js 的原因。

使用代码 

1. 首先,您必须安装 Ws.js 模块:

npm install ws.js   

2. 现在编写您的代码:

var ws = require('ws.js')
  , Http = ws.Http
  , Security = ws.Security
  , UsernameToken = ws.UsernameToken

var request =  '<Envelope xmlns="http://schemas.xmlsoap.org/soap/envelope/">' +
                  '<Header />' +
                    '<Body>' +
                      '<EchoString xmlns="http://tempuri.org/">' +
                        '<s>123</s>' +
                      '</EchoString>' +
                    '</Body>' +
                '</Envelope>'

var ctx =  { request: request 
           , url: "http://service/security"
           , action: "http://tempuri.org/EchoString"
           , contentType: "text/xml" 
           }

var handlers =  [ new Security({}, [new UsernameToken({username: "yaron", password: "1234"})])
                , new Http()
                ]

ws.send(handlers, ctx, function(ctx) {                    
  console.log("response: " + ctx.response);
})  

让我们分析一下这个例子。 以下代码导入相关的模块:

var ws = require('ws.js')
  , Http = ws.Http
  , Security = ws.Security
  , UsernameToken = ws.UsernameToken 

接下来的几行定义了 soap 信封和一些必要的信息,例如 url。 请注意,我们需要带外构建 soap - Ws.js 不是 soap 引擎。 然而,这通常很容易,因为我们通常有一个可用的 soap 示例。

var request =  '<Envelope xmlns="http://schemas.xmlsoap.org/soap/envelope/">' +
                  '<Header />' +
                    '<Body>' +
                      '<EchoString xmlns="http://tempuri.org/">' +
                        '<s>123</s>' +
                      '</EchoString>' +
                    '</Body>' +
                '</Envelope>'

var ctx =  { request: request 
           , url: "http://service/security"
           , action: "http://tempuri.org/EchoString"
           , contentType: "text/xml" 
           } 

接下来的几行是 ws-* 使用的核心。 我们定义了要在请求中使用的协议。 此特定请求使用 ws-security 标准并将其配置为发送用户名令牌。

var handlers =  [ new Security({}, [new UsernameToken({username: "yaron", password: "1234"})])
                , new Http()
                ]   

最后,这段代码发送请求(使用指定的协议)并处理响应。

ws.send(handlers, ctx, function(ctx) {                    
  console.log("response: " + ctx.response);
})    

生成的 soap 如下所示:

<Envelope xmlns="http://schemas.xmlsoap.org/soap/envelope/" xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:o="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
<Header>
  <o:Security>
    <u:Timestamp>
      <u:Created>2012-02-26T11:03:40Z</u:Created>
      <u:Expires>2012-02-26T11:08:40Z</u:Expires>
    </u:Timestamp>
    <o:UsernameToken>
      <o:Username>yaron</o:Username>
      <o:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">1234</o:Password>
    </o:UsernameToken>
  </o:Security> 
</Header>
<Body>
  <EchoString xmlns="http://tempuri.org/">
    <s>123</s>
  </EchoString>
</Body>      

MTOM 示例

发送 MTOM 附件非常相似。 我们只需要指定要发送的文件以及它对应的 soap 元素的路径:

//add attachment to the soap request
ws.addAttachment(ctx, "request", "//*[local-name(.)='File1']", 
                "me.jpg", "image/jpeg")
var handlers =  [ new Mtom()
                , new Http()
                ];   

完整的示例在这里

支持的协议

目前 Ws.js 支持以下协议:

  • MTOM
  • WS-Security(仅用户名令牌)
  • WS-Addressing(所有版本)
  • HTTP(S)

幕后花絮

Ws.js 使用职责链设计模式来调用不同的协议。 这是一个可扩展的模式,因此任何人都可以添加新的协议实现。 虽然这是 soap 堆栈的已知模式,但在 javascript 中实现它可能会有点棘手。 关键是每个处理程序都有一个 send() 和一个 receive() 方法。 发送实际上将控制权传递给下一个处理程序。 我们给那个处理程序一个回调方法。 该回调将调用我们的 receive(),传递给它上下文和我们得到的原始回调(下游处理程序对此一无所知)。 最好看看代码:

SecurityHandler.prototype.send = function(ctx, callback) {
  var self = this

  //actual logic here...

  this.next.send(ctx, function(ctx) { 
    self.receive(ctx, callback)
  })
}

SecurityHandler.prototype.receive = function(ctx, callback) {

  //optionally post processing here...

  callback(ctx)
}

var s = new SecurityHandler()
s.next = new HttpHandler()
s.send(ctx, function(ctx) {...})  
   

与许多 node 应用程序一样,Ws.js 也使用了一些外部模块。 它特别依赖于强大的 xml 处理库。 正如我在这里指出的那样,找到一个基于 dom 的 node.js xml 解析器,它可以在 windows 上工作,这并非易事。 我最终找到了 xmldomxpath.js

Ws.js 使用的其他值得注意的库是 node-formidablenode-bufferjs,它们在 mime 解析的上下文中很有帮助。

Ws.js 的未来

Ws.js 是一个不断发展的框架。 对于未来的版本,我计划添加更高级的安全标准,例如 X.509 数字签名和加密。 如果您有任何特殊要求,请从我的博客发送电子邮件给我。 如果您想提供帮助,请随时在 github 上 fork Ws.js - 这是发展 Ws.js 的最快方式。

更多信息

查看项目 github 页面

查看我的博客

查看我的 Twitter

我的博客给我发邮件

© . All rights reserved.