2008-09-02 7 views
88

Мой клиент попросил меня интегрировать сторонний API в свое приложение Rails. Единственная проблема заключается в том, что API использует SOAP. Ruby в основном отказался от SOAP в пользу REST. Они предоставляют Java-адаптер, который, по-видимому, работает с мостом Java-Ruby, но мы хотели бы сохранить его в Ruby, если это возможно. Я заглянул в soap4r, но, похоже, у него немного плохая репутация.Каков наилучший способ использования SOAP с Ruby?

Итак, как лучше всего интегрировать SOAP-вызовы в приложение Rails?

ответ

35

Мы использовали встроенный класс soap/wsdlDriver, который на самом деле является SOAP4R. Это собака медленная, но очень простая. SOAP4R, который вы получаете от gems/etc, - это просто обновленная версия того же самого.

Пример кода:

require 'soap/wsdlDriver' 

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

Вот об этом

+36

Отчасти причина, по которой это «Медленная собака», заключается в том, что вы создаете прокси каждый раз, когда вы подключаетесь к службе. Вы можете избежать этой боли, используя wsdl2ruby для постоянного создания прокси-сервера, а затем вызвать предварительно сгенерированный прокси-сервер. – 2009-02-20 22:56:49

+6

Мы могли бы, но это означало бы установку wsdl2ruby и т. Д. И т. Д. Иногда Dog Slow прекрасно :-) – 2010-11-07 19:29:53

2

Кент Сибилев из Datanoise также портированы библиотеки Rails ActionWebService на Rails 2.1 (и выше). Это позволяет вам показывать свои собственные SOAP-сервисы на основе Ruby. У него даже есть режим scaffold/test, который позволяет вам тестировать свои услуги с помощью браузера.

14

Мы переключились с Handsoap на Savon.

Описание: series of blog posts Сравнение двух клиентских библиотек.

159

Я построил Savon, чтобы как можно проще взаимодействовать с веб-сервисами SOAP через Ruby.
Я бы порекомендовал вам проверить его.

5

Я также рекомендую Savon http://wiki.github.com/rubiii/savon. Я провел слишком много часов, пытаясь разобраться с Soap4R, без каких-либо результатов. Большая нехватка функциональности, никаких документов.

Савон - это ответ для меня.

4

Только что мои вещи работают в течение 3 часов, используя Savon.

Приступая к работе документации на домашней странице Савон было очень легко следовать - и на самом деле соответствовало тому, что я видел (не всегда)

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

Надеется, что это помогает. Приветствия.

1

Я использовал SOAP в Ruby, когда мне пришлось сделать поддельный SOAP-сервер для моих приемочных тестов. Я не знаю, был ли это лучший способ подойти к проблеме, но это сработало для меня.

Я использовал Sinatra gem (я написал о создании смешных конечных точек с Sinatra here) для сервера, а также Nokogiri для XML-материала (SOAP работает с XML).

Итак, для начала я создал два файла (например, config.rb и answers.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 

Надеюсь, вы найдете это полезным!

Смежные вопросы