Domanda

Un mio cliente mi ha chiesto di integrare un'API di terze parti nella sua app Rails.L'unico problema è che l'API utilizza SOAP.Ruby ha sostanzialmente abbandonato SOAP a favore di REST.Forniscono un adattatore Java che apparentemente funziona con il bridge Java-Ruby, ma vorremmo mantenere tutto in Ruby, se possibile.Ho esaminato soap4r, ma sembra avere una reputazione leggermente negativa.

Allora qual è il modo migliore per integrare le chiamate SOAP in un'app Rails?

È stato utile?

Soluzione

Abbiamo usato il built-in soap/wsdlDriver classe, che in realtà è SOAP4R.È molto lento, ma davvero semplice.Il SOAP4R che ottieni da gems/etc è solo una versione aggiornata della stessa cosa.

Codice di esempio:

require 'soap/wsdlDriver'

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

Questo è tutto

Altri suggerimenti

ho costruito Savon per rendere l'interazione con i servizi web SOAP tramite Ruby il più semplice possibile.
Ti consiglierei di dargli un'occhiata.

Siamo passati da Handsoap a Savon.

Ecco un serie di post sul blog confrontando le due librerie client.

Lo consiglio anche Savon.Ho passato troppe ore cercando di gestire Soap4R, senza risultati.Grande mancanza di funzionalità, nessun documento.

Savon è la risposta per me.

Tentativo SOAP4R

E ne ho appena sentito parlare sul Podcast di Rails Envy (ep 31):

Ho appena fatto funzionare le mie cose in 3 ore usando Savon.

La documentazione introduttiva sulla home page di Savon è stata davvero facile da seguire e corrispondeva effettivamente a ciò che stavo vedendo (non sempre è così)

Kent Sibilev da Rumore dei dati aveva anche portato la libreria Rails ActionWebService su Rails 2.1 (e versioni successive).Ciò ti consente di esporre i tuoi servizi SOAP basati su Ruby.Ha anche una modalità impalcatura/test che ti consente di testare i tuoi servizi utilizzando un browser.

Stavo riscontrando lo stesso problema, sono passato a Savon e poi l'ho semplicemente testato su un WSDL aperto (ho usato http://www.webservicex.net/geoipservice.asmx?WSDL) Fino a qui, tutto bene!

https://github.com/savonrb/savon

Ho utilizzato SOAP in Ruby quando ho dovuto creare un server SOAP falso per i miei test di accettazione.Non so se questo fosse il modo migliore per affrontare il problema, ma per me ha funzionato.

Ho usato la gemma Sinatra (ho scritto sulla creazione di endpoint beffardi con Sinatra Qui) per server e anche Nokogiri per materiale XML (SOAP funziona con XML).

Quindi, per l'inizio ho creato due file (ad es.config.rb e risposte.rb) in cui ho inserito le risposte predefinite che il server SOAP restituirà.In config.rb Ho inserito il file WSDL, ma come stringa.

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

In risposte.rb Ho inserito esempi di risposte che il server SOAP restituirà per diversi scenari.

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

Quindi ora lascia che ti mostri come ho effettivamente creato il server.

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

Spero che lo troverai utile!

Ho utilizzato la chiamata HTTP come di seguito per chiamare un metodo 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")
*/

Spero che sia d'aiuto.Saluti.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top