Який найкращий спосіб використовувати SOAP із Ruby?


91

Мій клієнт попросив мене інтегрувати сторонній API в їх додаток Rails. Єдина проблема полягає в тому, що API використовує SOAP. Ruby в основному відмовився від SOAP на користь REST. Вони забезпечують адаптер Java, який, мабуть, працює з мостом Java-Ruby, але ми хотіли б зберегти все це в Ruby, якщо це можливо. Я розглядав soap4r, але, схоже, у нього трохи погана репутація.

То який найкращий спосіб інтегрувати дзвінки SOAP у програму Rails?

Відповіді:


36

Ми використовували вбудований soap/wsdlDriverклас, який насправді є SOAP4R. Це собака повільна, але насправді проста. SOAP4R, який ви отримуєте від gems / etc - це просто оновлена ​​версія того самого.

Приклад коду:

require 'soap/wsdlDriver'

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

Ось і все


37
Частково причиною, чому це "Dog Slow", є те, що ви створюєте проксі-сервер кожного разу, коли ви підключаєтесь до служби. Ви можете уникнути цього болю, використовуючи wsdl2ruby для постійного створення проксі-сервера, а потім викликати попередньо створений проксі-сервер.
Стів Віт,

6
Ми могли б, але це означало б встановлення wsdl2ruby тощо і так далі. Іноді Собака Повільно добре :-)
Оріон Едвардс

1
Якщо вам потрібно створити проксі-класи для Savon, ви можете слідувати підходу kredmer щодо побудови методів мила на льоту за допомогою SoapUI, щоб заповнити імена методів і не потрібно будувати власний парсер wsdl :). Замість того, щоб зберігати всі методи в пам'яті, ви можете писати у файл, особливо якщо у вас багато тонн.
Деян

3
04/2015: Soap4r мертвий, веб-сайт не працює. Здається, на даний момент Савон є загальним вибором.
Puce

Я порпався в цьому просторі і виявив soap4r-нг, що по - , як і раніше підтримується github.com/rubyjedi/soap4r
Ghoti

170

Я створив Savon, щоб максимально спростити взаємодію з веб-сервісами SOAP через Ruby.
Я рекомендую вам перевірити це.


5
+1 для savon, не для того, щоб бити soap4r - але я мав дуже поганий досвід роботи з ним. Відсутність хорошої документації та надто громіздка.
konung

1
Приємно! Світ SOAP у рубінах покращився з того часу, коли минулого разу мені довелося використовувати Soap4R для цього (~ 18 місяців тому)
madlep

чи може хтось із вас, будь ласка, допомогти мені вдарити сабле-api за допомогою savon? У мене є код, який savon надає мені методи, використовуючи wsdl SOAP, але я не можу відправити запит за допомогою savon у форматі xml.
Джай Кумар Раджпут


5

Я також рекомендую Савон . Я витратив занадто багато годин, намагаючись мати справу з Soap4R, без результатів. Велика відсутність функціональних можливостей, відсутність документації.

Савон - це відповідь для мене.



3

Щойно мої речі працюють протягом 3 годин, використовуючи Savon.

Документація з початку роботи на домашній сторінці Савона була дуже простою - і насправді відповідала тому, що я бачив (не завжди так)


2

Кент Сібільов з Datanoise також переніс бібліотеку Rails ActionWebService на Rails 2.1 (і вище). Це дозволяє вам відкрити власні сервіси SOAP на основі Ruby. У нього навіть встановлений режим тестування, який дозволяє перевірити свої послуги за допомогою браузера.


2

Я використовував SOAP у Ruby, коли мені доводилося робити фальшивий сервер SOAP для моїх приймальних тестів. Не знаю, чи це був найкращий спосіб підійти до проблеми, але це спрацювало для мене.

Я використовував самоцвіт Sinatra (я писав про створення знущальних кінцевих точок за допомогою Sinatra тут ) для сервера, а також 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

Сподіваюсь, це вам стане в нагоді!



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

Сподіваюся, це допоможе. Ура.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.