RubyでSOAPを使用する最良の方法は何ですか?


91

私のクライアントから、サードパーティのAPIをRailsアプリに統合するように依頼されました。唯一の問題は、APIがSOAPを使用することです。Rubyは基本的にSOAPを削除してRESTを支持しています。それらは明らかにJava-Rubyブリッジで動作するJavaアダプターを提供しますが、可能であればすべてをRubyで維持したいと考えています。私はsoap4rを調べましたが、評判がやや悪いようです。

では、SOAP呼び出しをRailsアプリに統合する最良の方法は何でしょうか。

回答:


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を使用して永続的にプロキシを構築し、事前に生成されたプロキシを呼び出すことで、この問題を回避できます。
スティーブウィート

6
できますが、これはwsdl2rubyなどをインストールすることを意味します。時には犬のスローがうまくいく:-)
Orion Edwards

1
Savonのプロキシクラスを構築する必要がある場合は、SoapUIを使用してオンザフライでsoapメソッドを構築するクレドマーのアプローチに従い、カスタムwsdlパーサーを構築する必要なくメソッド名を入力できます:)。すべてのメソッドをメモリに保存する代わりに、特にトンがある場合は、ファイルに書き込むことができます。
Dejan

3
2015年4月:Soap4rが停止し、ウェブサイトがダウンしています。現時点では、Savonが一般的な選択のようです。
Puce、

私はこのスペースを掘り下げていて、soap4r-ngを発見しました。それはまだ維持されていますgithub.com/rubyjedi/soap4r
Ghoti

170

私は、Rubyを介してSOAP Webサービスと簡単にやり取りできるようにSavonを作成しました。
ぜひチェックしてみてください。


5
soap4rをbashするのではなく、savonの+1。良いドキュメントがなく、面倒すぎる。
konung

1
いいね!rubyのSOAPの世界は、これを行うために前回Soap4Rを使用しなければならなかったとき(〜18か月前)から改善されました
madlep

savonを使用してsaber apiをヒットするのを手伝ってくれませんか?SOAPのwsdlを使用してメソッドを提供するsavonのコードがありますが、xml形式でsavonを使用してリクエストを送信できません。
Jai Kumar Rajput


5

私もサボンをお勧めします。結果なしで、Soap4Rに対処しようと何時間も費やしました。機能の大きな欠如、ドキュメントなし。

サボンは私のための答えです。



3

Savonを使用して3時間以内に私の機能を動作させました。

SavonのホームページにあるGetting Startedドキュメントは非常に簡単に追跡でき、実際に私が見ているものと一致していました(常にそうであるとは限りません)


2

ケントSibilev Datanoiseはまた、Railsの2.1(以上)へのRails ActionWebServiceライブラリを移植していました。これにより、独自のRubyベースのSOAPサービスを公開できます。彼は、ブラウザを使用してサービスをテストできるscaffold / testモードも備えています。


2

受け入れテストのために偽のSOAPサーバーを作成する必要があったとき、私はRubyでSOAPを使用しました。これが問題に対処するための最良の方法であったかどうかはわかりませんが、私にとってはうまくいきました。

私はサーバーにSinatra gem(ここでSinatraを使用してモックエンドポイントを作成することについて書きました)を使用し、XMLのものにはNokogiriを使用しました(SOAPはXMLで動作しています)。

そのため、最初に2つのファイル(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>'

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

これがお役に立てば幸いです。



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

それが役に立てば幸い。乾杯。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.