soap客户端
2009-12-03选择
ruby带有soap4r的插件,可以用于访问web service服务接口,但不支持basic_auth、WS-Security
因此选用handsoap作为客户端插件
安装
#curb在window下安装很麻烦,改为指定httpclient #sudo gem install handsoap curb nokogiri httpclient --no-ri --no-rdoc sudo gem install handsoap nokogiri httpclient --no-ri --no-rdoc #如果安装curb过程报cannot find -lcur错误,则运行 sudo apt-get install libcurl4-openssl-dev
#environment.rb中加入 config.gem 'handsoap', :lib => 'handsoap', :source => "http://gems.github.com" #curb在window下安装很麻烦,改为指定httpclient,environment.rb中最底部加入 Handsoap.http_driver=:httpclient
使用
#生成客户端类 script/generate handsoap http://192.168.1.20:8081/cmis/webService/ciisStatService?wsdl
配置管理员需要配置的地方在这里(用户、密码、接口地址)
#生成的连接地址加入environments/production.rb中
CIIS_USERNAME = 'cogent'
CIIS_PASSWORD = 'cogent'
CIIS_STAT_SERVICE_IMPL_SERVICE_ENDPOINT = {
:uri => 'http://192.168.1.20:8081/cmis/webService/ciisStatService',
:version => 1
}
#script/console s = Ciis::PopService.find_pop '%' #获取列表对象 s.list #获取列表对象中的内容 s.list.first.name #获取属性值 s.size
调试
使用soapui访问webservice接口,确保服务正常
为了监控客户端与服务器的交互内容,可使用tcpmon架设代理
注意,连接接口时要设置用户名密码,双击某个接口方法的请求(一般为request1),点击弹出的右边窗口左下方的[Aut],输入用户名、密码
然后在Request1窗口中点击右键,选择[Add WSS Username Token],会看到请求的xml中增加了用户名、密码
问题
#按照handsoap官方说明无法实现ws-security的访问
#提示Security processing failed (actions mismatch)
#经过尝试,以下调用是成功的
def on_create_document(doc)
#register namespaces for the request
doc.alias 'tns', 'http://ws.stat.wsif.cogent.com/'
doc.alias 's', 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd'
header = doc.find("Header")
header.add "s:Security" do |s|
#增加此节点,否则会报错
s.add "s:UsernameToken" do |t|
t.add "s:Username", "cogent"
t.add "s:Password", "cogent"
end
end
end
[第二个问题]开发环境下报错:ArgumentError: A copy of Ciis::PopService has been removed from the module tree but is still active!
#重现步骤
script/console
Ciis::PopService.find_pop('%')
reload!
#再次执行报错
Ciis::PopService.find_pop('%')
产品环境下没问题,但由于开发环境下class会被缓存,而handsoap静态方法引用了实例对象
在handsoap源代码中发现以下语句
@@instance = {}
def self.instance
@@instance[self.to_s] ||= self.new
end
def self.method_missing(method, *args, &block)
if instance.respond_to?(method)
instance.__send__ method, *args, &block
else
super
end
end
因此在开发环境下需要重载instance静态方法
#config/initializers/fixed_handsoap_reload_error.rb
unless development?
module Handsoap
class Service
def self.instance
self.new
end
end
end
end
#测试是否解决问题了 script/console #确保每次获取的实例对象不一样 Ciis::PopService.instance Ciis::PopService.instance