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 input/namespace issue #37

Closed
gitpig opened this issue Feb 14, 2010 · 28 comments
Closed

wsdl input/namespace issue #37

gitpig opened this issue Feb 14, 2010 · 28 comments

Comments

@gitpig
Copy link

gitpig commented Feb 14, 2010

I'm having a problem using Savon with a wsdl service provided by Telnic (dev.telnic.org). I'm finding that I have to explicitly name the requested operation and its namespace. Example:

Savon::SOAP.version = 2

client = Savon::Client.new("https://telhosting.opensrs.com/client?wsdl")
client.request.basic_auth("user", "pass")

# Doesn't work
#client.list_domains

# Works
client.list_domains do |soap|
    soap.input     = "listDomainsRequest"
    soap.namespace = "http://xmlns.telnic.org/ws/nsp/client/domain/types-1.0"
end
@rubiii
Copy link
Contributor

rubiii commented Feb 14, 2010

unfortunately, parsing all these different kinds of wsdl documents is not the easiest thing to do. but i'll try to get yours working without having to explicitly name the soap input. will get back to you asap.

btw. i appreciate any help in improving the wsdl parser.

@gitpig
Copy link
Author

gitpig commented Feb 14, 2010

Thanks for the quick response. I understand parsing wsdl is not easy :)

@rubiii
Copy link
Contributor

rubiii commented Feb 20, 2010

from what i've seen now, the telnic wsdl is split into several documents and savon does not support this right now. since getting and parsing the wsdl is not recommended for production and downloading several documents would be even more inefficient ...

i would suggest to disable the wsdl for speed and loc improvements:

client.listDomainsRequest! do |soap|
  soap.namespace = "http://xmlns.telnic.org/ws/nsp/client/domain/types-1.0"
end

but i'll leave this issue open for now. i'm definitely thinking about improving the wsdl parser, but as i said: you should always disable it for production.

@ibothwell
Copy link

I think this is part of the same issue.

Aside from the WSDL parser issue - Even disabling the WSDL for production the code creating the XML Body of the SOAP Payload assumes the "wsdl" namespace for the input method which is not always the case.

module Savon;class SOAP;
....
# Adds a SOAP XML body to a given +xml+ Object.
private
  def xml_body(xml)
    xml.env(:Body) do
      xml.tag!(:wsdl, *input_array) { xml << (@body.to_soap_xml rescue @body.to_s) }
    end
   end
...
end;end;

In the SOAP Class the :wsdl namespace is forced on the input method. An example of a case which requires a different namespace have a look at the ParlayX Third Party Call Service:
http://en.wikipedia.org/wiki/Parlay_X
http://docbox.etsi.org//TISPAN/Open/OSA/ParlayX30.html

In the case of the above service a it requires the method to be "n1" not "wsdl".

@rubiii
Copy link
Contributor

rubiii commented Mar 27, 2010

thinking about a proper way to solve this issue.

@natikgadzhi
Copy link

Running into the same issue.
Actually, i can write a couple of lines of code to get optional namespace for the operation name here.

It'll solve the issue with xml_body method.

@reneneumann
Copy link

I have the same issue, but even going one step further I would need something like this so I would have to change the both namespaces (for the envelope and the body)

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:sim="http://dvr.avocent.com/simple-asset">
soapenv:Header
<wsse:Security xmlns:wsse='http://docs.oasis-open.org/wss/2004/01/oasis-200401-ws
</wsse:Security>
/soapenv:Header
soapenv:Body
sim:QueryRequest
some more stuff here
/sim:QueryRequest
/soapenv:Body
/soapenv:Envelope

@jarib
Copy link

jarib commented May 12, 2010

Same issue here.

@rubiii
Copy link
Contributor

rubiii commented May 17, 2010

i hear you guys! thinking about the best way to customize this convention. suggestions welcome.

@reneneumann
Copy link

I modified my version so that it will work for me, as I need both the default behavior and my "special" version I added another variable which i can set and that dose the job for me. Unfortunately is currently my option not as flexible as I hoped as I had to hard code the xml body call to do either sim or the default. I'm relatively new to ruby and i did not spent hours on it either, but if the xml call be done with an variable I believe the issue can be reasonably easy solved. I can sent you my version if you like.

@rubiii
Copy link
Contributor

rubiii commented Jun 8, 2010

quick survey: would you need to changed or disable the :wsdl namespace globally (for all client instances), per client instance or per request?

@moogle
Copy link

moogle commented Jun 8, 2010

Seems like per-client disabling would be the most robust. I'm sure there's a fair amount of people who will connect to multiple services, but each service probably only needs to be customized once.

As with reneneumann, I would also request the ability to modify the Envelope/Body namespaces and attributes. I'm trying to connect to a NuSOAP (php) service, and they expect something like this:

<SOAP-ENV:Envelope xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:tns="http://example.com/soapservice">
 <SOAP-ENV:Body>
  <ns1:someMethod xmlns:ns1="http://example.com/soapservice">
    payload...
  </ns1:someMethod>
 </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

@jschoolcraft
Copy link

@rubiii I think per client instance, at least in my case.

Any movement on this topic?

@rosyman
Copy link

rosyman commented Jul 8, 2010

Having access to the soap body would alleviate this too. I am being bit by this hitting a proprietary soap service. Has anyone found a workaround?
<env:Envelope xmlns:env='http://schemas.xmlsoap.org/soap/envelope/'>env:Header/env:Headerenv:Body<env:Fault xmlns:env='http://schemas.xmlsoap.org/soap/envelope/'>env:Clientorg.xml.sax.SAXParseException: The prefix "wsdl" for element "wsdl:TspOrder" is not bound./env:Fault/env:Body/env:Envelope
Savon::SOAPFault: (env:Client) org.xml.sax.SAXParseException: The prefix "wsdl" for element "wsdl:TspOrder" is not bound.
from /usr/local/lib/ruby/gems/1.8/gems/savon-0.7.9/lib/savon/response.rb:141:in handle_soap_fault' from /usr/local/lib/ruby/gems/1.8/gems/savon-0.7.9/lib/savon/response.rb:81:ininitialize'
from /usr/local/lib/ruby/gems/1.8/gems/savon-0.7.9/lib/savon/client.rb:95:in new' from /usr/local/lib/ruby/gems/1.8/gems/savon-0.7.9/lib/savon/client.rb:95:inmethod_missing'
from ./CfmsSimulator.rb:20:in sendsoap' from ./CfmsSimulator.rb:148:increate_order'

@rosyman
Copy link

rosyman commented Jul 8, 2010

On a similar note, is there a way to pass in a hash to soap.body, and have it end up CamelCase, not lowerCamelCase?

@eimermusic
Copy link

I thought I'd take it a step further as in the namespace issues when creating the soap body xml (as: http://github.com/rubiii/savon/issues#issue/37/comment/168261).

I have a service that uses the namespace all the way. That is not only on the root tag of the body but on all tags in both body and header. The body therefore needs to specify the namespace on each tag like this:

<env:Body>
  <foo:InputAction xmlns:foo="http://example.com/soap/foo">
    <foo:SomeTag>hello</foo:SomeTag>
    ...
  </foo:InputAction>
</env:Body>

I have not found a way to make Savon do this automagically but I think it would be a cool addition once the issues discussed above are addressed.

What I do is specify the hash keys as strings instead of symbols. No big deal, really.

body = {
  'foo:SomeTag' => 'hello'
}

Of-course I also have a monkey-patch that lets me replace the "wsdl" sent to xml.tag!

I interact with SOAP as little as possible because it is such a mess of a "standard" so I don't know how common this type of namespace is. Prioritize it as you see fit is all I am saying. :)

@khoenshel
Copy link

I am connecting to a service where the WSDL sets elementFormDefault="qualified". From what I understand, this value can be set to 'qualified' or 'unqualified'. An over-simplified description: when set to 'qualified', all of the elements in the SOAP request need to be fully qualified, as in eimermusic's example above. This behavior is specified here: http://www.w3.org/TR/xmlschema-0/#QualLocals. An explicit setting for this style of output in the SOAP body would be nice, but if the WSDL file specifies that the elements should all be fully namespace qualified, then the elements in the SOAP body should be fully qualified. For now, I have to place the namespace in the hash keys...

@eimermusic
Copy link

the service I connect to does not have a wsdl, but that sounds like a good attribute to react to.

@jjmartres
Copy link

any updates about this issue ?

@rubiii
Copy link
Contributor

rubiii commented Oct 4, 2010

the input/namespace issue is fixed in the dev branch. these changes will be released as a beta gem asap. the dev branch contains quite a lot of changes, so hopefully you guys will be able to test and provide feedback.

@rubiii
Copy link
Contributor

rubiii commented Oct 4, 2010

khoenshel: i opened a new issue for the elementFormDefault="qualified" comment at: http://github.com/rubiii/savon/issues/issue/91

@rubiii
Copy link
Contributor

rubiii commented Oct 29, 2010

please try savon 0.8.0.beta.1

@jjmartres
Copy link

Hi

The 0.8.0 has solved the problem for me. Rubii has done a great job on this version.

@derpepe
Copy link

derpepe commented Nov 17, 2010

Well, one thing that isn't "pretty":

Because I only need a custom namespace and not "wsdl:", I only use the endpoint-parameter.
With Savon 0.8.0 beta 1 I have to use
client = Savon::Client.new do
wsdl.endpoint = "http://localhost:8888/"
wsdl.namespace = ''
end
and my request contains my addition to the soap.namespaces-Attribute:
response = client.request(:customns, 'MyAction') {
soap.namespaces['xmlns:customns'] = "http://example.com/soap/"
soap.body {
...

IMO it would be much nicer if I could use
ids = Savon::Client.new do
soap.endpoint = "http://localhost:8888/"
soap.namespaces['xmlns:customns'] = "http://example.com/soap/"
end
and later just
response = client.request(:customns, 'MyAction') {
soap.body {
...
for the request.

It feels strange to give client.request a namespace as first parameter, and declare it 'later' in the block.

What do you think about this?

@rubiii
Copy link
Contributor

rubiii commented Nov 23, 2010

i'm not really sure if the following example is what you need:

client = Savon::Client.new do
  wsdl.endpoint = "http://localhost:8888/"
  wsdl.namespace = "http://namespace.localhost"
end

response = client.request :customns, :my_action do
  soap.body = "<some>xml</some>"
end

creates the following request:

<env:Envelope
    xmlns:customns="http://namespace.localhost"
    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>
    <customns:myAction><some>xml</some></customns:myAction>
  </env:Body>
</env:Envelope>

if that's not what you're trying to do, please post a sample request as a gist/pastie and i'll try to work out the savon code for you.

@eimermusic
Copy link

just a small fyi. (I haven't had the time to try 0.8 beta yet, sorry if this is supported already)

I have found services that require the root body tag to be void of any namespace. E.g. outputting:
xml

Since it looks like custom namespaces work I thought i'd be a shame to forget the edge-case of no namespace.

@rubiii
Copy link
Contributor

rubiii commented Nov 27, 2010

thanks for the feedback. v0.8.0 supports both custom and no namespaces.

@rubiii
Copy link
Contributor

rubiii commented Dec 20, 2010

released v0.8.0 which should solve this problem.

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