falc410 / pysimplesoap

Automatically exported from code.google.com/p/pysimplesoap
0 stars 0 forks source link

Client is unable to understand WSDL when namespace is defined #155

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
What steps will reproduce the problem?
1. Any WSDL containing <wsdl:part> elements with a an xmlns attribute.
2. Use a PySimpleSoap client to call a port that uses one of the above messages.
3.

What is the expected output? What do you see instead?

Given ITestService with 3 service ports:
   1. SayHello(string), returns string
   2. BaseId(), returns int
   3. BaseBaseId(), returns int

In the WSDL, the messages are defined as below.  Notice that the first two 
wsdl:part's reference different xml namespaces, q1 & q2.

    <wsdl:message name="ITestService_BaseBaseId_InputMessage">
        <wsdl:part name="parameters" element="q1:BaseBaseId" xmlns:q1="http://tempuri.org/basebaseservice"/>
    </wsdl:message>
    <wsdl:message name="ITestService_BaseBaseId_OutputMessage">
        <wsdl:part name="parameters" element="q2:BaseBaseIdResponse" xmlns:q2="http://tempuri.org/basebaseservice"/>
    </wsdl:message>
    <wsdl:message name="ITestService_BaseId_InputMessage">
        <wsdl:part name="parameters" element="q3:BaseId" xmlns:q3="http://tempuri.org/baseservice"/>
    </wsdl:message>
    <wsdl:message name="ITestService_BaseId_OutputMessage">
        <wsdl:part name="parameters" element="q4:BaseIdResponse" xmlns:q4="http://tempuri.org/baseservice"/>
    </wsdl:message>
    <wsdl:message name="ITestService_SayHello_InputMessage">
        <wsdl:part name="parameters" element="tns:SayHello"/>
    </wsdl:message>
    <wsdl:message name="ITestService_SayHello_OutputMessage">
        <wsdl:part name="parameters" element="tns:SayHelloResponse"/>
    </wsdl:message>

Test Case 1:

from pysimplesoap.client import SoapClient
client = SoapClient(wsdl="http://localhost:7072/TestService.svc?singleWsdl")

print client.SayHello('dan')  #works fine
print client.BaseId()         #works fine
print client.BaseBaseId()     #error below

Traceback (most recent call last):
  File "C:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\IDE\Extensions\Microsoft\Python Tools for Visual Studio\2.0\visualstudio_py_util.py", line 76, in exec_file
    exec(code_obj, global_variables)
  File "{PATH}\ClientIssue.py", line 6, in <module>
    print client.BaseBaseId()
  File "c:\pysimplesoap-1a9cc78e97a4\pysimplesoap\client.py", line 177, in <lambda>
    return lambda *args, **kwargs: self.wsdl_call(attr, *args, **kwargs)
  File "c:\pysimplesoap-1a9cc78e97a4\pysimplesoap\client.py", line 336, in wsdl_call
    self.qualified = operation['qualified']
KeyError: u'qualified'

Test Case 2:

from pysimplesoap.client import SoapClient
client = SoapClient(wsdl="http://localhost:7072/TestService.svc?singleWsdl")

for service in client.services.values():
    for port in service['ports'].values():
        print port['location']
        for op in port['operations'].values():
            print 'Name:', op['name']
            print 'Docs:', op['documentation'].strip()
            print 'SOAPAction:', op['action']
            print 'Input', op['input'] # args type declaration
            print 'Output', op['output'] # returns type declaration

This outputs:

    http://127.0.0.1:7072/TestService.svc
    Name: SayHello
    Docs: None
    SOAPAction: http://tempuri.org/ITestService/SayHello
    Input {'SayHello': {u'name': <type 'str'>}}
    Output {'SayHelloResponse': {u'SayHelloResult': <type 'str'>}}

    Name: BaseBaseId
    Docs: None
    SOAPAction: http://tempuri.org/basebase/IBaseBaseService/BaseBaseId
    Input {u'ITestService_BaseBaseId_InputMessage': {u'parameters': None}}           <----PARAMETER SHOULD NOT BE 'None'
    Output {u'ITestService_BaseBaseId_OutputMessage': {u'parameters': None}}         <----PARAMETER SHOULD NOT BE 'None'

    Name: BaseId
    Docs: None
    SOAPAction: http://tempuri.org/IBaseService/BaseId
    Input {'BaseId': {u'id': <type 'int'>}}
    Output {'BaseIdResponse': {u'BaseIdResult': <type 'int'>}}

The correct output should be:

    http://127.0.0.1:7072/TestService.svc
    Name: SayHello
    Docs: None
    SOAPAction: http://tempuri.org/ITestService/SayHello
    Input {'SayHello': {u'name': <type 'str'>}}
    Output {'SayHelloResponse': {u'SayHelloResult': <type 'str'>}}

    Name: BaseBaseId
    Docs: None
    SOAPAction: http://tempuri.org/IBaseBaseService/BaseBaseId
    Input {'BaseBaseId': {u'id': <type 'int'>}}                                  <----CORRECT PARAMETER 
    Output {'BaseBaseIdResponse': {u'BaseBaseIdResult': <type 'int'>}}           <----CORRECT PARAMETER 

    Name: BaseId
    Docs: None
    SOAPAction: http://tempuri.org/IBaseService/BaseId
    Input {'BaseId': {u'id': <type 'int'>}}
    Output {'BaseIdResponse': {u'BaseIdResult': <type 'int'>}}

What version of the product are you using? On what operating system?
PySimpleSoap 1.14, Windows 7, WCF Service

Please attach the related WSDL (if any), a small code fragment to reproduce
and provide any additional information below.

WSDL and C# WCF service code attached.
The issue seems to be happening in simplexml.py get_namespace_uri... The method 
only searches for all xmlns defined in the parent wsdl:definitions.  Instead, 
it should be recursively searching from the current element all the way up to 
wsdl:definitions.  I considered making a patch but wanted to see if this is 
known issue first.

Original issue reported on code.google.com by d.li...@gmail.com on 16 Sep 2014 at 8:57

Attachments:

GoogleCodeExporter commented 9 years ago
Thanks very much for the detailed report!

Feel free to submit a patch if you want to propose a fix, PR are always welcome 
;-)

I can review this after finishing the XMLSEC WSSE support that I'm working on, 
but I'll have to set up a .NET environment to test it (I didn't faced this 
issue with other WCF services I have access), so it will be faster if you can 
confirm and fix it directly.

Original comment by reingart@gmail.com on 16 Sep 2014 at 9:14

GoogleCodeExporter commented 9 years ago
Apologies, it appears that the issue is actually in client.py 
xml_tree_to_services() method.  When iterating through wsdl.messages, the 
following line

     type_uri = wsdl.get_namespace_uri(type_ns)

should be changed to 

     type_uri = part.get_namespace_uri(type_ns)

This allows the get_namespace_uri method to properly search the current element 
for the namespace uri, and recurse all the way up to the root node.

I can create a pull request if you'd like.

Original comment by d.li...@gmail.com on 16 Sep 2014 at 9:14

GoogleCodeExporter commented 9 years ago
Please, feel free to go ahead an create a PR, thanks in advance!

Original comment by reingart@gmail.com on 16 Sep 2014 at 9:30

GoogleCodeExporter commented 9 years ago
I added pull request #20 on GitHub.

Original comment by d.li...@gmail.com on 17 Sep 2014 at 2:19

GoogleCodeExporter commented 9 years ago
This issue was closed by revision f6925e9e692e.

Original comment by reingart@gmail.com on 17 Sep 2014 at 5:59

GoogleCodeExporter commented 9 years ago
This issue was closed by revision 5ce260640547.

Original comment by reingart@gmail.com on 17 Sep 2014 at 5:59

GoogleCodeExporter commented 9 years ago
Thanks very much!

I've also added you to the contributor group in this site (and given 
permissions to edit wiki/issues just in case), feel free to contact me if you 
need anything else

Original comment by reingart@gmail.com on 17 Sep 2014 at 6:01