将SOAP与Ruby一起使用的最佳方法是什么?


91

我的一个客户要求我将第三方API集成到他们的Rails应用中。唯一的问题是API使用SOAP。Ruby基本上放弃了SOAP,而选择了REST。他们提供了一个显然可以与Java-Ruby桥接器一起使用的Java适配器,但如果可能的话,我们希望将其全部保留在Ruby中。我调查过soap4r,但声誉似乎有些差。

那么将SOAP调用集成到Rails应用程序中的最佳方法是什么?

Answers:


36

我们使用了内置soap/wsdlDriver类,它实际上是SOAP4R。狗很慢,但是真的很简单。从gems / etc获得的SOAP4R只是同一事物的更新版本。

示例代码:

require 'soap/wsdlDriver'

client = SOAP::WSDLDriverFactory.new( 'http://example.com/service.wsdl' ).create_rpc_driver
result = client.doStuff();

就是这样


37
之所以称为“ Dog Slow”,部分原因是您每次连接到服务时都在构建代理。您可以通过使用wsdl2ruby永久构建代理,然后调用预生成的代理来避免这种麻烦。
Steve Weet 09年

6
我们可以,但这意味着安装wsdl2ruby等。有时候“慢狗”是好的:-)
Orion Edwards 2010年

1
如果您需要为Savon构建代理类,则可以遵循kredmer的方法在SoapUI的帮助下即时构建soap方法来填充方法名称,而不必构建自定义的wsdl解析器:)。无需将所有方法存储在内存中,您可以写入文件,特别是如果您有大量文件。
Dejan

3
2015年4月4日:Soap4r已死,网站已关闭。目前,Savon似乎是常见的选择。
Puce

我一直在四处在这个空间里,发现SOAP4R-NG,即仍然维持github.com/rubyjedi/soap4r
Ghoti

170

我构建了Savon,以使通过Ruby与SOAP Web服务的交互尽可能容易。
我建议您检查一下。


5
为savon +1,而不是重击soap4r-但我的经验确实很差。缺少好的文档,而且太麻烦了。
konung 2010年

1
真好!自从我上次不得不使用Soap4R进行此操作以来(大约18个月前),Ruby中的SOAP世界已经得到了改善
madlep 2011年

你们中的任何人都可以帮助我使用savon打saber api吗?我有一个代码,savon使用SOAP的wsdl为我提供了方法,但是我无法使用xml格式的savon发送请求。
Jai Kumar Rajput




3

使用Savon,我的东西在3个小时之内就可以工作了。

Savon主页上的“入门指南”文档非常易于理解,并且与我所看到的完全匹配(并非总是如此)


2

从肯特Sibilev Datanoise也移植了Rails ActionWebService库的Rails 2.1(及以上)。这使您可以公开自己的基于Ruby的SOAP服务。他甚至有一个脚手架/测试模式,该模式允许您使用浏览器测试服务。


2

当我不得不为接受测试制作一个假的SOAP服务器时,我在Ruby中使用过SOAP。我不知道这是否是解决问题的最佳方法,但这对我有用。

我已经使用了Sinatra gem(我曾在此处写过有关使用Sinatra创建模拟端点的内容)用于服务器,还使用过Nokogiri处理XML的东西(SOAP正在使用XML)。

因此,首先,我创建了两个文件(例如config.rb和response.rb),在其中放置了SOAP服务器将返回的预定义答案。在config.rb中,我已将WSDL文件放入字符串中。

@@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服务器针对不同场景返回的响应提供了样本。

@@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">
                <a:Error>Invalid username and password</a:Error>
                <a:ObjectInformation i:nil="true"/>
                <a:Response>false</a:Response>
            </LoginResult>
        </LoginResponse>
    </s:Body>
</s:Envelope>"

现在,让我向您展示如何真正创建服务器。

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

希望对您有所帮助!



0

我使用了如下的HTTP调用来调用SOAP方法,

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")
*/

希望能帮助到你。干杯。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.