【问题标题】:What's the best way to use SOAP with Ruby?将 SOAP 与 Ruby 结合使用的最佳方式是什么?
【发布时间】:2010-09-07 14:30:00
【问题描述】:

我的一个客户要求我将第 3 方 API 集成到他们的 Rails 应用程序中。唯一的问题是 API 使用 SOAP。 Ruby 基本上放弃了 SOAP,转而使用 REST。他们提供了一个显然可以与 Java-Ruby 桥配合使用的 Java 适配器,但如果可能的话,我们希望将它全部保留在 Ruby 中。我查看了soap4r,但它的名声似乎有点差。

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

【问题讨论】:

    标签: ruby-on-rails ruby soap


    【解决方案1】:

    我也推荐Savon。我花了太多时间尝试处理 Soap4R,但没有结果。功能严重不足,没有文档。

    萨翁是我的答案。

    【讨论】:

      【解决方案2】:

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

      我使用 Sinatra gem(我写过关于使用 Sinatra here 创建模拟端点)用于服务器,还使用Nokogiri 用于 XML 东西(SOAP 与 XML 一起使用)。

      所以,一开始我创建了两个文件(例如 config.rb 和responses.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>'
      

      responses.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
      

      希望对您有所帮助!

      【讨论】:

        【解决方案3】:

        我已经使用如下 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")
        */
        

        希望对您有所帮助。干杯。

        【讨论】:

        • 感谢您发布此内容。我只是这样做!保持简单:-)
        【解决方案4】:

        我遇到了同样的问题,切换到 Savon,然后在一个开放的 WSDL 上进行了测试(我使用了http://www.webservicex.net/geoipservice.asmx?WSDL),到目前为止一切顺利!

        https://github.com/savonrb/savon

        【讨论】:

          【解决方案5】:

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

          示例代码:

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

          就是这样

          【讨论】:

          • 这是“狗慢”的部分原因是您每次连接到服务时都在构建代理。您可以通过使用 wsdl2ruby 永久构建代理,然后调用预先生成的代理来避免这种痛苦。
          • 我们可以,但这意味着安装 wsdl2ruby 等等。有时 Dog Slow 很好 :-)
          • 如果您需要为 Savon 构建代理类,您可以按照 kredmer's 方法在 SoapUI 的帮助下即时构建肥皂方法来填充方法名称,而无需构建自定义wsdl 解析器:)。您可以写入文件而不是将所有方法存储在内存中,尤其是在您有大量方法的情况下。
          • 04/2015:Soap4r 已死,网站已关闭。看来 Savon 是目前的普遍选择。
          • 我一直在这个空间中挖掘并发现了soap4r-ng,它仍在维护github.com/rubyjedi/soap4r
          【解决方案6】:

          我构建了Savon 以尽可能轻松地通过 Ruby 与 SOAP Web 服务进行交互。
          我建议你检查一下。

          【讨论】:

          • +1 表示 savon,而不是 bash soap4r - 但我对它的体验非常糟糕。缺乏良好的文档并且过于繁琐。
          • 不错!自从上次我不得不使用 Soap4R 来做这件事(大约 18 个月前)之后,ruby 中的 SOAP 世界得到了改进
          • 谁能帮我用 savon 打 saber api 吗?我有一个代码,可以为我提供使用 SOAP 的 wsdl 的方法,但我无法使用 savon 以 xml 格式发送请求。
          【解决方案7】:

          使用 Savon 在 3 小时内完成了我的工作。

          Savon 主页上的入门文档非常容易理解 - 并且实际上与我所看到的相符(并非总是如此)

          【讨论】:

            【解决方案8】:

            我们从 Handsoap 切换到 Savon。

            这是一个series of blog posts 比较两个客户端库。

            【讨论】:

              【解决方案9】:

              来自Datanoise 的 Kent Sibilev 还将 Rails ActionWebService 库移植到 Rails 2.1(及更高版本)。 这允许您公开自己的基于 Ruby 的 SOAP 服务。 他甚至有一个脚手架/测试模式,允许您使用浏览器测试您的服务。

              【讨论】:

                【解决方案10】:

                试试 SOAP4R

                我刚刚在 Rails Envy 播客(第 31 集)上听说了这个:

                【讨论】:

                  猜你喜欢
                  • 2013-12-20
                  • 2019-05-26
                  • 2016-03-01
                  • 1970-01-01
                  • 2010-10-29
                  • 1970-01-01
                  • 2010-09-06
                  • 2018-07-14
                  • 2011-04-11
                  相关资源
                  最近更新 更多