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?
Cambiamos de Handsoap a Savon.
Aquí hay una serie de publicaciones de blog que comparan las dos bibliotecas de clientes.
Estaba teniendo el mismo problema, cambié a Savon y luego solo lo probé en un WSDL abierto (utilicé http://www.webservicex.net/geoipservice.asmx?WSDL ) y hasta ahora ¡todo bien!
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.
Pruebe SOAP4R
Y acabo de enterarme de esto en Rails Envy Podcast (ep 31):
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