2010-02-19 8 views
8

Estoy intentando acceder a un servicio SOAP que no controlo. Una de las acciones se llama ProcessMessage. Seguí el ejemplo y generé una solicitud SOAP, pero recibí un error diciendo que la acción no existe. Indagué el problema en la forma en que se genera el cuerpo del sobre.¿Por qué se interpone el espacio de nombres "wsdl" en el nombre de la acción cuando se utiliza savon para la comunicación de ruby ​​soap?

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

Eso ProcessMessage etiqueta debe ser:

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

Eso es lo que es cuando se genera mediante la aplicación de ejemplo de Java, y funciona. Esa etiqueta es la única diferencia entre lo que genera mi aplicación Ruby y la aplicación Java de muestra. ¿Hay alguna manera de deshacerse del espacio de nombre "wsdl:" frente a esa etiqueta y agregar un atributo como ese. Salvo eso, ¿hay alguna manera de forzar la acción para que no se genere simplemente pasando como una cadena como el resto del cuerpo?

Aquí está mi código:

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 

Probé handsoap pero no es compatible con HTTPS y es confuso. Intenté soap4r pero es aún más confuso que handsoap.

+0

un billete para esta estaba abierta en: http://github.com/rubiii/savon/issues#issue/39 – rubiii

+0

Hola Nick, has llegado en cualquier parte con esto ya que estoy viendo el mismo problema. –

+0

Hola Steve. Puse esta parte del proyecto en el estado de espera, ya que había otras funciones más importantes que necesitaban implementación, y esta era una lista "agradable de tener". Voy a probar tu solución más tarde y ver si funciona. ¡Gracias por dejarme saber tú! – konung

Respuesta

4

Steve, ¿ves ese wsdl: delante de la etiqueta ProcessMessage? - Pensé que era lo único que me estaba tirando, pero no es así (por cierto, es difícil de encontrar en soap.rb en Savon lib en la línea 160). Eso incluso si no lo espacifico en soap.namespaces - es difícil de generar y se adjunta en el xml final. Lo cual no está permitido por mi servicio.

Mientras que el xml que se genera es un xml válido, no está completo por los requisitos del servicio con el que trato de hablar. Es decir: en XML generado,

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

etiqueta falta, también, necesito PayloadManifest en la cabecera, además necesito wsu: creada y WSU: expira en mi wsse: etiqueta, pero no se implementan, etc. , etc. un montón de otras pequeñas peculiaridades que son demasiado específicas para mi caso. Sin embargo, soap tiene un método privado = xml_body. También soap lib en el método to_xml está comprobando si @xml_body ya estaba configurado, antes de generar su propio xml. Así que terminé modificando levemente el comportamiento del jabón. haciendo soap.xml_body = accesible públicamente. Así que pude hacer:

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 

que finalmente funciona !!!!

Sugeriré esto a rubii - si esta opción está disponible que resolverá muchos casos raros - donde la gente puede generar su xml personalizado y usar el resto de savon lib.

+0

Esa sería una buena solución, creo. Descubrí que IIS/.net se quejaba de la falta de un espacio de nombres, pero no le importaba si había una directiva en la parte superior del archivo. Buena suerte, fue muy doloroso llegar a ese punto. –

10

Necesita pasar una matriz a soap.input cuyo segundo elemento es un hash que contiene los detalles del espacio de nombres.

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

Esto debería garantizar que termine con la declaración de espacio de nombre como un atributo para el elemento principal.

Es probable que también termina con una declaración de espacio de nombres antes del elemento al igual que

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

pero esto no fue un problema para mí, fue la ausencia del atributo de espacio de nombres que era el problema, no el presencia del espacio de nombres antes del elemento.

+0

Steve. Gracias por su mensaje; no es mi solución, pero me hizo pensar y mirar los registros con más cuidado. Ver mi propia respuesta. No hay suficiente espacio aquí en los comentarios. :-) – konung

+0

Gracias a su solución funcionó un encanto justo ahora cuando estaba teniendo exactamente el mismo problema. –

+0

Su solución funcionó para mí. ¡Me faltaban las xmlns dentro de la acción! Todavía obtengo el espacio de nombres wsdl: dentro del cuerpo, pero no afecta la solicitud SOAP. – pedrofalcaocosta

7

Para mi servicio web necesitaba deshacerme del espacio de nombres "wsdl" encima de la solución de Steve.

Probado con 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 
+2

+1 para gotcha # 2 .. – abhijit

+0

brilliant answer. –

+0

Gotcha 2 me estaba matando, gracias Kenji! – zrl3dx

Cuestiones relacionadas