rails ruby-on-rails ruby soap

ruby on rails - rails - ¿Cuál es la mejor manera de usar SOAP con Ruby?



savon soap rails (10)

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

La documentación de Getting Started en la página principal de Savon fue muy fácil de seguir, y en realidad coincidía con lo que estaba viendo (no siempre es el caso)

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.

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




He usado SOAP en Ruby cuando tuve que crear un servidor falso 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 la gema Sinatra (escribí sobre la creación de puntos finales burladores con Sinatra here ) para el servidor y también Nokogiri para material XML (SOAP está trabajando con XML).

Entonces, para el comienzo 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 puse ejemplos de respuestas que el servidor SOAP devolverá 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 realmente 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 esto te sea útil!


He usado la llamada HTTP como a continuación para 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 eso ayude. Aclamaciones.


Kent Sibilev de Datanoise también había portado la biblioteca Rails ActionWebService a Rails 2.1 (y 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.



También recomiendo a Savon . Pasé demasiadas horas tratando de lidiar con Soap4R, sin resultados. Gran falta de funcionalidad, no doc.

Savon es la respuesta para mí.


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


Usamos la clase incorporada 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 de ejemplo:

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

Eso es todo