2008-09-02 30 views
88

Un cliente mío me ha pedido que integre una API de terceros en su aplicación Rails. El único problema es que la API usa SOAP. Ruby básicamente ha dejado SOAP a favor de REST. Proporcionan un adaptador Java que aparentemente funciona con el puente Java-Ruby, pero nos gustaría mantenerlo todo en Ruby, si es posible. Investigué en soap4r, pero parece tener una reputación un poco mala.¿Cuál es la mejor manera de usar SOAP con Ruby?

¿Cuál es la mejor manera de integrar llamadas SOAP en una aplicación de Rails?

Respuesta

35

Utilizamos la clase incorporada en soap/wsdlDriver, que en realidad es SOAP4R. Es un perro lento, pero realmente simple. El SOAP4R que obtienes de gems/etc es solo una versión actualizada de lo mismo.

código Ejemplo:

require 'soap/wsdlDriver' 

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

Eso es todo

+36

Parte de la razón por la cual esto es "Perro lento" es que está construyendo el proxy cada vez que se conecta al servicio. Puede evitar este dolor usando wsdl2ruby para construir el proxy de forma permanente y luego llamar al proxy pregenerado. –

+6

Podríamos, pero eso significaría instalar wsdl2ruby y demás. A veces Dog Slow está bien :-) –

+1

Si necesita crear clases proxy para Savon, puede seguir [kredmer's] (https://github.com/kredmer/memotoo/blob/master/lib/memotoo/main.rb) enfoque de construir métodos de jabón sobre la marcha con la ayuda de SoapUI para poblar nombres de métodos y no tener que crear un analizador wsdl personalizado :). En lugar de almacenar todos los métodos en la memoria, puede escribir en el archivo, especialmente si tiene toneladas. – Dejan

2

Kent Sibilev de Datanoise también había portado la biblioteca rieles ActionWebService a los carriles 2.1 (o superior). Esto le permite exponer sus propios servicios SOAP basados ​​en Ruby. Incluso tiene un modo de andamio/prueba que le permite probar sus servicios usando un navegador.

159

Creé Savon para hacer que interactuar con SOAP webservices a través de Ruby sea lo más fácil posible.
Te recomiendo que lo veas.

+5

+1 para savon, no para bash soap4r, pero tuve una experiencia realmente mala con él . La falta de buena documentación y demasiado engorroso. – konung

+1

¡Agradable! El mundo SOAP en ruby ​​ha mejorado desde la última vez que tuve que usar Soap4R para hacer esto (~ 18 meses atrás) – madlep

+0

¿alguno de ustedes puede ayudarme a presionar sabre api usando savon? Tengo un código que me proporciona los métodos que usan wsdl de SOAP pero no puedo enviar la solicitud usando savon en formato xml. –

4

Acabo de hacer que mis cosas funcionen en 3 horas usando Savon.

La documentación de Introducción en la página de Savon era muy fácil de seguir - y en realidad emparejado lo que estaba viendo (no siempre es el caso)

0

he utilizado llamada HTTP, como a continuación llamar a un método 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") 
*/ 

espero que ayude. Aclamaciones.

1

He usado SOAP en Ruby cuando tuve que crear un falso servidor SOAP para mis pruebas de aceptación. No sé si esta fue la mejor manera de abordar el problema, pero funcionó para mí.

He usado Sinatra gem (Escribí sobre la creación de extremos de burla con Sinatra here) para el servidor y también Nokogiri para cosas de XML (SOAP está trabajando con XML).

Así que, para empezar, he creado dos archivos (por ejemplo, config.rb y responses.rb) en los que he puesto las respuestas predefinidas que devolverá el servidor SOAP. En config.rb He puesto el archivo WSDL, pero como una cadena.

@@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>' 

En responses.rb he puesto muestras para que las respuestas servidor SOAP volverá para diferentes escenarios.

@@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>" 

Así que ahora déjame mostrarte cómo he creado el servidor.

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 

Espero que le resulte útil.

Cuestiones relacionadas