Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

"wsdl" namespace interjected into action name - breaking service, related to issue #36 #39

Closed
konung opened this issue Feb 18, 2010 · 11 comments

Comments

@konung
Copy link

konung commented Feb 18, 2010

Hi, rubiii

Thank you for a cool library. I was trying to see if we could use it and ran into a stumbling block. I'm trying to access a SOAP service i don't control. One of the actions is called ProcessMessage. I follow example and generate a SOAP request, but I get an error back saying that the action doesn't exist. I traced the problem to the way the body of the envelope is generated.

<env:Envelope ... ">
    <env:Header>
        <wsse:Security ... ">
            <wsse:UsernameToken ...">
                <wsse:Username>USUSER</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>     

That ProcessMessage tag should be :

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

That's what it is when it is generated by the sample java app, and it works. That tag is the only difference between what my ruby app generates and the sample java app. Is there any way to get rid of the "wsdl:" namesaplce in front of that one tag and add an attribute like that. Barring that, is there a way force the action not to be generated from the name of the soap action called, but be passed as s tring like the rest of the body?

Here is my code.

require 'rubygems'
require 'savon'
client = Savon::Client.new "https://myservice?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 in the final xml output
soap.input = "ProcessMessage" #makes no difference in the final xml output

#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

Thank you

P.S.:
I would really appreciate any pointers. I like the simplicity of savon and I don't wont to be dragged into soap4r, (handsoap doesn't support wsse, or at least I couldn't find y indication of that)

@rubiii
Copy link
Contributor

rubiii commented Feb 20, 2010

if possible, please send me the uri to the wsdl document, so i can have a look without too much guessing. thanks,

@rubiii
Copy link
Contributor

rubiii commented Feb 20, 2010

ok thanks. there are several things you need to get right here.

  1. you don't need to set soap.input when not using Savon::WSDL. you can just call the method you want to use on Savon::Client and the name of the method is used as soap.input.

    response = client.Process_message!
    
  2. you also don't need to specify your soap.body as an xml string. savon supports namespaces when you're specifying your hash keys as strings adding the namespaces yourself.

    soap.body = { "wsdl:payload" => "..." }
    

so here's something that worked for me:

client = Savon::Client.new "https://gmservices.pp.gm.com/pwbservices/ProcessMessage_1"
response = client.Process_message! do | soap, wsse |
  wsse.username = "USER"
  wsse.password = "password"
  soap.namespace = "http://www.starstandards.org/webservices/2005/10/transport"
  soap.action = "http://www.starstandards.org/webservices/2005/10/transport/operations/ProcessMessage"
  soap.body = { "wsdl:payload" => "..." }
end

hope it helps!

ps. i suggest using soapUI, looking at the xml and raw request, the documentation for savon and trying to align both requests.

@rubiii
Copy link
Contributor

rubiii commented Mar 6, 2010

closing this issue, since the author is not responding any more.

@steveweet
Copy link

Hi Rubii, I'm having exactly the same issues as the creator of this issue.

This is the XML I need to generate in order for the Web Service to accept the request

<env:Envelope xmlns:wsdl="http://www.example.com/ExampleWS/clsExampleWS"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:env="http://schemas.xmlsoap.org/soap/envelope/">
env:Body


Version_1_23_1
RomadUser
Romad1



/env:Body
/env:Envelope

This is the XML I am currently generating

<env:Envelope xmlns:wsdl="http://www.example.com/ExampleWS/clsExampleWS"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:env="http://schemas.xmlsoap.org/soap/envelope/">
env:Body
wsdl:ListTransmitters

Version_1_23_1
RomadUser
Romad1


/wsdl:ListTransmitters
/env:Body
/env:Envelope

The only difference is the namespace on the main input Item. I have to be able to pass the namespace name or the SOAP Server will reject it.

This is the code I am using to generate the XML, sorry the company has an NDA in place and I can not give you access to the WSDL.

response = client.ListTransmitters! do |soap|
soap.namespaces["xmlns:wsdl"] = "http://www.example.com/ExampleWS/clsExampleWS"

soap.action = "http://www.example.com/exampleWS/clsExampleWS/ListTransmitters"
soap.namespace = "http://www.example.com/ExampleWS/clsExampleWS"
soap.input = "ListTransmitters"

soap.body = {
  "listTransmittersRequestKey" => {
    "ServiceVersion" => "Version_1_23_1",
    "UserName" => "RomadUser",
    "Password" => "Romad1",
    "TransmitterFilter" => nil,
    :order! => %w[ServiceVersion UserName Password TransmitterFilter]
  }
}

end

Is there any way of passing an attribute to the soap.input element?

@steveweet
Copy link

I've found the answer to this. The solution is to pass an array to soap.input the second element of which is a hash as follows :-

soap.input = [ "ListTransmitters", { "xmlns" => "http://www.example.com/ExampleWS/clsExampleWS" } ]

@konung
Copy link
Author

konung commented Mar 17, 2010

I finally solved this. Here is my post from stackoverflow:

Steve, you see that wsdl: in front of ProcessMessage tag? - I thought that was the only thing that was throwing me off but its not ( by the way it's hard set in soap.rb in Savon lib on line 160). That even if I don't spacify it in soap.namespaces - it's hard generated and attached in final xml. Which is not allowed by my service.

While the xml that is generated is a valid xml - it's not complete by the requirments of the service I'm trying to talk to. I.e.: in generated xml,

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

tag is missing, also, I need PayloadManifest in the header,plus I need wsu:created and wsu:expires in my wsse: tag, but they are not implemented, etc., etc. a bunch of other little quirks that are too specific to my case. However soap has a private method = xml_body. Also soap lib in to_xml method is checking whether @xml_body was already set, before generating it's own xml. So I ended up slighly modifying behavior of soap. by making soap.xml_body = publicly accessable. So I was able to do:

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

Which finally works!!!!

I'll suggest this to rubii - if this option becomes available that will solve a lot rare cases - where people can generate their custom xml and use the rest of savon lib.

@rubiii
Copy link
Contributor

rubiii commented Mar 17, 2010

added a fix for this for the next release: http://github.com/rubiii/savon/commit/93535eb7d1acb257a4ed8ece9630bc3ad3f30fe4

also you will see some of your improvements being integrated soon. thanks again!

@rubiii
Copy link
Contributor

rubiii commented Mar 21, 2010

@rubiii
Copy link
Contributor

rubiii commented Mar 21, 2010

released version 0.7.6 containg a fix for this problem. please update.

@konung
Copy link
Author

konung commented Mar 31, 2010

Rubii, just wanted to let you know - i just tested 0.7.6 against my use case and it worked just fine. Thank you.

@rubiii
Copy link
Contributor

rubiii commented Mar 31, 2010

great. appreciate the feedback!

calamitas pushed a commit to calamitas/savon that referenced this issue Jun 7, 2011
added an attr_accessor for :xml_body to the soap object. so you can now specify your very own request xml as a string and savon won't force you to use it's conventions.
This issue was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

3 participants