我的一个客户要求我将第三方API集成到他们的Rails应用中。唯一的问题是API使用SOAP。 Ruby基本上放弃了SOAP,而选择了REST。他们提供了一个显然可以与Java-Ruby桥接器一起使用的Java适配器,但如果可能的话,我们希望将其全部保留在Ruby中。我调查过soap4r,但声誉似乎有些差。
那么将SOAP调用集成到Rails应用程序中的最佳方法是什么?
我构建了Savon,以使通过Ruby与SOAP Web服务的交互尽可能容易。
我建议您检查一下。
我们使用了内置的soap/wsdlDriver类,它实际上是SOAP4R。
狗很慢,但是真的很简单。从gems / etc获得的SOAP4R只是同一事物的更新版本。
示例代码:
1 2 3 4
| require 'soap/wsdlDriver'
client = SOAP::WSDLDriverFactory.new( 'http://example.com/service.wsdl' ).create_rpc_driver
result = client.doStuff(); |
就是这样
我们从Handsoap切换到Savon。
这里是一系列比较两个客户端库的博客文章。
我也推荐Savon。我花了太多时间试图处理Soap4R,但没有结果。严重缺乏功能,没有文档。
Savon是我的答案。
尝试SOAP4R
我刚刚在Rails Envy播客(ep 31)上听说过:
只需使用Savon在3小时内就能完成我的工作。
Savon主页上的《入门指南》文档非常易于理解-确实与我所看到的相符(并非总是如此)
当我必须为接受测试制作一个假SOAP服务器时,我在Ruby中使用了SOAP。我不知道这是否是解决问题的最佳方法,但这对我有用。
我已经使用了Sinatra gem(我在这里写过有关使用Sinatra创建模拟端点的内容)以及服务器的Nokogiri(用于XML的东西)(SOAP正在使用XML)。
因此,首先,我创建了两个文件(例如config.rb和response.rb),在其中放置了SOAP服务器将返回的预定义答案。
在config.rb中,我已将WSDL文件放入字符串中。
1 2 3 4 5 6 7 8
| @@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="http://schemas.xmlsoap.org/wsdl/">
.......
</wsdl:definitions>' |
在response.rb中,我为SOAP服务器针对不同场景返回的响应提供了样本。
1 2 3 4 5 6 7 8 9 10 11
| @@login_failure ="<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body>
<LoginResponse xmlns="http://tempuri.org/">
<LoginResult xmlns:a="http://schemas.datacontract.org/2004/07/WEBMethodsObjects" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
Invalid username and password</a:Error>
false</a:Response>
</LoginResult>
</LoginResponse>
</s:Body>
</s:Envelope>" |
因此,现在让我向您展示如何真正创建服务器。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
| require 'sinatra'
require 'json'
require 'nokogiri'
require_relative 'config/config.rb'
require_relative 'config/responses.rb'
after do
# cors
headers({
"Access-Control-Allow-Origin" =>"*",
"Access-Control-Allow-Methods" =>"POST",
"Access-Control-Allow-Headers" =>"content-type",
})
# json
content_type :json
end
#when accessing the /HaWebMethods route the server will return either the WSDL file, either and XSD (I don't know exactly how to explain this but it is a WSDL dependency)
get"/HAWebMethods/" do
case request.query_string
when 'xsd=xsd0'
status 200
body = @@xsd0
when 'wsdl'
status 200
body = @@wsdl
end
end
post '/HAWebMethods/soap' do
request_payload = request.body.read
request_payload = Nokogiri::XML request_payload
request_payload.remove_namespaces!
if request_payload.css('Body').text != ''
if request_payload.css('Login').text != ''
if request_payload.css('email').text == some username && request_payload.css('password').text == some password
status 200
body = @@login_success
else
status 200
body = @@login_failure
end
end
end
end |
希望对您有所帮助!
Datanoise的Kent Sibilev也已将Rails ActionWebService库移植到Rails 2.1(及更高版本)。
这使您可以公开自己的基于Ruby的SOAP服务。
他甚至具有脚手架/测试模式,可让您使用浏览器测试服务。
我已经使用了如下所示的HTTP调用来调用SOAP方法,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
| require 'net/http'
class MyHelper
def initialize(server, port, username, password)
@server = server
@port = port
@username = username
@password = password
puts"Initialised My Helper using #{@server}:#{@port} username=#{@username}"
end
def post_job(job_name)
puts"Posting job #{job_name} to update order service"
job_xml ="<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns="http://test.com/Test/CreateUpdateOrders/1.0">
<soapenv:Header/>
<soapenv:Body>
<ns:CreateTestUpdateOrdersReq>
<ContractGroup>ITE2</ContractGroup>
<ProductID>topo</ProductID>
<PublicationReference>#{job_name}</PublicationReference>
</ns:CreateTestUpdateOrdersReq>
</soapenv:Body>
</soapenv:Envelope>"
@http = Net::HTTP.new(@server, @port)
puts"server:" + @server +"port :" + @port
request = Net::HTTP::Post.new(('/XISOAPAdapter/MessageServlet?/Test/CreateUpdateOrders/1.0'), initheader = {'Content-Type' => 'text/xml'})
request.basic_auth(@username, @password)
request.body = job_xml
response = @http.request(request)
puts"request was made to server" + @server
validate_response(response,"post_job_to_pega_updateorder job", '200')
end
private
def validate_response(response, operation, required_code)
if response.code != required_code
raise"#{operation} operation failed. Response was [#{response.inspect} #{response.to_hash.inspect} #{response.body}]"
end
end
end
/*
test = MyHelper.new("mysvr.test.test.com","8102","myusername","mypassword")
test.post_job("test_201601281419")
*/ |
希望有帮助。干杯。
我遇到了同样的问题,切换到Savon,然后在开放的WSDL上对其进行了测试(我使用了http://www.webservicex.net/geoipservice.asmx?WSDL),到目前为止一切顺利!
https://github.com/savonrb/savon