9 votes

Pourquoi l'espace de nom "wsdl" est-il injecté dans le nom de l'action lorsque l'on utilise savon pour la communication ruby soap ?

J'essaie d'accéder à un service SOAP que je ne contrôle pas. L'une des actions s'appelle ProcessMessage . J'ai suivi l'exemple et généré une requête SOAP, mais j'ai reçu en retour une erreur indiquant que l'action n'existe pas. J'ai trouvé la cause du problème dans la façon dont le corps de l'enveloppe est généré.

<env:Envelope ... ">
    <env:Header>
        <wsse:Security ... ">
            <wsse:UsernameToken ...">
                <wsse:Username>USER</wsse:Username>
                    <wsse:Nonce>658e702d5feff1777a6c741847239eb5d6d86e48</wsse:Nonce>
                    <wsu:Created>2010-02-18T02:05:25Z</wsu:Created>
                    <wsse:Password ... >password</wsse:Password>
            </wsse:UsernameToken>
        </wsse:Security>
    </env:Header>
    <env:Body>
        <wsdl:ProcessMessage>
            <payload>
                ......
            </payload>
        </wsdl:ProcessMessage>
    </env:Body>
</env:Envelope>     

Ce ProcessMessage devrait être :

    <ProcessMessage xmlns="http://www.starstandards.org/webservices/2005/10/transport">

C'est ce qu'il est lorsqu'il est généré par l'exemple d'application Java, et cela fonctionne. Cette balise est la seule différence entre ce que mon application Ruby génère et l'exemple d'application Java. Existe-t-il un moyen de se débarrasser de la balise "wsdl:" devant cette seule balise et ajouter un attribut comme celui-ci. Sinon, y a-t-il un moyen de forcer l'action à ne pas être générée en la passant simplement comme une chaîne de caractères comme le reste du corps ?

Voici mon code :

require 'rubygems'
require 'savon'
client = Savon::Client.new "https://gmservices.pp.gm.com/ProcessMessage?wsdl"

response = client.process_message! do | soap, wsse |
wsse.username = "USER"
wsse.password = "password"
soap.namespace = "http://www.starstandards.org/webservices/2005/10/transport" #makes no difference
soap.action = "ProcessMessage" #makes no difference
soap.input = "ProcessMessage" #makes no difference

#my body at this point is jsut one big xml string

soap.body = "<payload>...</payload>" 
# putting <ProccessMessage> tag here doesn't help as it just creates a duplicate tag in the body, since Savon keeps interjecting  <wsdl:ProcessMessage> tag.

  end

J'ai essayé handsoap mais il ne supporte pas HTTPS et est confus. J'ai essayé soap4r mais c'est encore plus confus que handsoap.

10voto

Steve Weet Points 15395

Vous devez passer un tableau à soap.input dont le deuxième élément est un hachage contenant les détails de l'espace de nom.

soap.input = [ 
  "ProcessMessage", 
  {"xmlns" => "http://www.starstandards.org/webservices/2005/10/transport"}
]

Cela devrait vous permettre d'obtenir la déclaration de l'espace de nom en tant qu'attribut de l'élément principal.

Vous vous retrouverez probablement avec une déclaration d'espace de nom avant l'élément, comme suit

<env:Body>
    <wsdl:ProcessMessage xmlns="........." >
        <payload>
            ......
        </payload>
    </wsdl:ProcessMessage>
</env:Body>

mais ce n'était pas un problème pour moi, c'était l'absence de l'attribut namespace qui était le problème, et non la présence de l'espace de nom avant l'élément.

7voto

Kenji Noguchi Points 581

Pour mon service web, je devais me débarrasser de l'option "wsdl" par-dessus la solution de Steve.

Testé avec Savon 0.9.6 :

client = Savon::Client.new "https://example.com/webservice/account.asmx?WSDL"
response = client.request "GetAccount" do
  # Gotcha 1: set default namespace for body elements
  soap.input = ["GetAccount", {"xmlns" => "https://example.com/webservice/"}]
  soap.body = {
    "AccountID" => 1234
  }
  # Gotcha 2: get rid of namespace declaration of body elements
  soap.element_form_default = :unqualified
  # Gotcha 3: set SOAPAction different from default
  http.headers["SOAPAction"] = '"https://example.com/webservice/GetAccount"'
end

4voto

Nick Gorbikoff Points 3144

Steve, tu vois le wsdl : devant la balise ProcessMessage ? - Je pensais que c'était la seule chose qui me perturbait mais ce n'est pas le cas (d'ailleurs c'est défini dans soap.rb dans Savon lib à la ligne 160). Même si je ne le spacifie pas dans soap.namespaces - il est généré en dur et attaché dans le xml final. Ce qui n'est pas autorisé par mon service.

Bien que le fichier xml généré soit valide, il n'est pas conforme aux exigences du service auquel j'essaie de me connecter. C'est-à-dire : dans le xml généré,

<?xml version="1.0" encoding="UTF-8"?>

est manquant, de même, j'ai besoin de PayloadManifest dans l'en-tête, et j'ai besoin de wsu:created et wsu:expires dans mon tag wsse :, mais ils ne sont pas implémentés, etc., etc. un tas d'autres petites bizarreries qui sont trop spécifiques à mon cas. Cependant, soap a une méthode privée = xml_body. De plus la librairie soap dans la méthode to_xml vérifie si @xml_body a déjà été défini, avant de générer son propre xml. J'ai donc fini par modifier légèrement le comportement de soap. en rendant soap.xml_body = accessible au public. Ainsi j'ai pu faire :

response = client.process_message! do |soap| 
soap.action = "http://www.starstandards.org/webservices/2005/10/transport/operations/ProcessMessage"
soap.xml_body = "MY XML STRING GENERATED ELSEWHERE GOES HERE"
end

Ce qui fonctionne finalement !!!!

Je vais suggérer cela à rubii - si cette option devient disponible, cela résoudra beaucoup de cas rares - où les gens peuvent générer leur xml personnalisé et utiliser le reste de la librairie savon.

0voto

David Points 57

J'ai passé des heures à essayer de trouver une solution pour m'en débarrasser :

<wsdl:ProcessMessage>
</wsdl:ProcessMessage>

Cela fait ce que je voulais :

client = Savon.client(
 :no_message_tag => true
)

Testé dans Savon 2.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X