Question

Un de mes clients m'a demandé d'intégrer une API tierce dans son application Rails.Le seul problème est que l'API utilise SOAP.Ruby a essentiellement abandonné SOAP au profit de REST.Ils fournissent un adaptateur Java qui fonctionne apparemment avec le pont Java-Ruby, mais nous aimerions tout conserver en Ruby, si possible.J'ai étudié Soap4r, mais il semble avoir une mauvaise réputation.

Alors, quelle est la meilleure façon d'intégrer les appels SOAP dans une application Rails ?

Était-ce utile?

La solution

Nous avons utilisé le soap/wsdlDriver classe, qui est en fait SOAP4R.C'est très lent, mais vraiment simple.Le SOAP4R que vous obtenez de gems/etc n'est qu'une version mise à jour de la même chose.

Exemple de code :

require 'soap/wsdlDriver'

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

C'est à peu près ça

Autres conseils

j'ai construit Savon pour rendre l'interaction avec les services Web SOAP via Ruby aussi simple que possible.
Je vous recommande de le vérifier.

Nous sommes passés de Handsoap à Savon.

Voici une série d'articles de blog comparer les deux bibliothèques clientes.

Je recommande également Savon.J'ai passé trop d'heures à essayer de gérer Soap4R, sans résultats.Gros manque de fonctionnalité, pas de doc.

Savon est la réponse pour moi.

Essayer SOAP4R

Et je viens d'en entendre parler sur le podcast Rails Envy (ep 31) :

Je viens de faire fonctionner mes affaires en 3 heures avec Savon.

La documentation de démarrage sur la page d'accueil de Savon était vraiment facile à suivre - et correspondait en fait à ce que je voyais (pas toujours le cas)

Kent Sibilev de Bruit de données avait également porté la bibliothèque Rails ActionWebService vers Rails 2.1 (et supérieur).Cela vous permet d'exposer vos propres services SOAP basés sur Ruby.Il dispose même d'un mode échafaudage/test qui vous permet de tester vos services à l'aide d'un navigateur.

J'avais le même problème, je suis passé à Savon et je l'ai ensuite testé sur un WSDL ouvert (j'ai utilisé http://www.webservicex.net/geoipservice.asmx?WSDL) Et jusqu'ici tout va bien!

https://github.com/savonrb/savon

J'ai utilisé SOAP dans Ruby lorsque j'ai dû créer un faux serveur SOAP pour mes tests d'acceptation.Je ne sais pas si c'était la meilleure façon d'aborder le problème, mais cela a fonctionné pour moi.

J'ai utilisé Sinatra Gem (j'ai écrit sur la création de points de terminaison moqueurs avec Sinatra ici) pour le serveur et aussi Nokogiri pour les éléments XML (SOAP travaille avec XML).

Donc, pour commencer, j'ai créé deux fichiers (par ex.config.rb et réponses.rb) dans lequel j'ai mis les réponses prédéfinies que le serveur SOAP renverra.Dans config.rb J'ai mis le fichier WSDL, mais sous forme de chaîne.

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

Dans réponses.rb J'ai mis des exemples de réponses que le serveur SOAP renverra pour différents scénarios.

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

Alors maintenant, laissez-moi vous montrer comment j'ai réellement créé le serveur.

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

J'espère que vous trouverez cela utile !

J'ai utilisé l'appel HTTP comme ci-dessous pour appeler une méthode 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")
*/

J'espère que cela aide.Acclamations.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top