Complex Type issue with SOAPpy - python

I'm trying to access a function defined in my WSDL from HP Server Automation, I'm able to get servers/etc, but not able to pull anything that takes a server reference specifically via SOAPpy.
import SOAPpy
from SOAPpy import WSDL
from SOAPpy import structType
SOAPpy.Config.debug=1
server = WSDL.Proxy('ServerService.wsdl')
serverRef = structType(name='self', typed=0)
serverRef._addItem('id',SOAPpy.longType(19250001))
print server.getCustAttr(serverRef,key='HPSW_ED_win32_diskspace',useScope=False)
The SOAP envelope generated from this code looks like this:
*** Outgoing SOAP ******************************************************
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope
SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:xsd2="http://www.w3.org/2000/10/XMLSchema"
xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance"
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsd="http://www.w3.org/1999/XMLSchema"
>
<SOAP-ENV:Body>
<ns1:getCustAttr xmlns:ns1="http://server.opsware.com" SOAP-ENC:root="1">
<xsd:self>
<id xsi:type="xsd2:long">19250001</id>
</xsd:self>
<useScope xsi:type="xsd:boolean">False</useScope>
<key xsi:type="xsd:string">HPSW_ED_win32_diskspace</key>
</ns1:getCustAttr>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
And it should look like this ( runs successfully via SOAPUI):
<soapenv:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ser="http://server.opsware.com">
<soapenv:Header/>
<soapenv:Body>
<ser:getCustAttr soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<self xsi:type="ser:ServerRef">
<id xsi:type="xsd:long">19250001</id>
</self>
<key xsi:type="soapenc:string" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/">HPSW_ED_win32_diskspace</key>
<useScope xsi:type="xsd:boolean">False</useScope>
</ser:getCustAttr>
</soapenv:Body>
</soapenv:Envelope>
I believe the issue is that the xsi:type="ser:ServerRef" is not set, and not really sure how to do that with SOAPpy...

there are two different types of soap styles(RPC literal and Document literal),looks like the mentioned soap server just supports RPC
i saw this problem with soappy and suds. after some tests and benchmarks,i found the problem.
ASP.NET and soappy. you need produce a rpc envelop with python instead document literal envelop style.
just ZSI(The Zolera Soap Infrastructure) works with asp.net and complex types.
this command generates the client proxy for you:
wsdl2py http://terraservice.net/TerraService.asmx?WSDL
and you can import generated modules in your code and use the web methods.

Related

spyne - generating xsd for requests that does not require explicit statement of namespace for each input parameter

At present, my Spyne-based WSGI application generates XSDs for requests like the following:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:aso="asoapns">
<soapenv:Header/>
<soapenv:Body>
<aso:findSpace>
<aso:Volume>?</aso:Volume>
<aso:Area>?</aso:Area>
<aso:Atmosphere>?</aso:Atmosphere>
<aso:Location>?</aso:Location>
</aso:findSpace>
</soapenv:Body>
</soapenv:Envelope>
Would it be possible to make the input parameters able to be specified without a namespace specifically? i.e. For example:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:aso="asoapns">
<soapenv:Header/>
<soapenv:Body>
<aso:findSpace>
<Volume>?</Volume>
<Area>?</Area>
<Atmosphere>?</Atmosphere>
<Location>?</Location>
</aso:findSpace>
</soapenv:Body>
</soapenv:Envelope>
Or is this a natural requirement of a SOAP API?
Specifying 'soft' validation as opposed to 'lxml' in the application specification allows requests to not need specific namespaces listed.
application = Application( [API],
tns = soap_namespace,
in_protocol=Soap11(validator='soft'),
out_protocol=Soap11())

change XML evelope settings in suds

I'm trying to acces a SOAP API. This works while using SOAP-UI as a test environment.
Now I want to implement it in Suds/Python. The actual request suds makes differs in the soap:Envelope element. I have no idea how to set it so it works.
The correct request made by SOAP-UI
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:plur="pluriform:works:datatypes:DagstatenApp-0">
<soap:Header/>
<soap:Body>
...
</soap:Body>
</soap:Envelope>
with the rather minimal python code:
from suds.client import Client
client = Client(url)
client.set_options(soapheaders=(user, passwd)
result = client.service.getWhatEver(arg1, arg2)
I get this:
<SOAP-ENV:Envelope xmlns:ns0="pluriform:works:datatypes:DagstatenApp-0" xmlns:ns1="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Header/>
<ns1:Body>
...
</ns1:Body>
</SOAP-ENV:Envelope>
Which if I copy-paste it in SOAP-UI. I get this error:
<soapenv12:Text xml:lang="EN">Systeemmelding 6EDB::4844 XML Type error (code 19060)
Systeemmelding 6EDB::4844 XML Type error (code 19060)
Error: Systeemmelding XML Type error (6EDB::4844)
XML Type mismatch. Expected tag [http://www.w3.org/2003/05/soap-envelope]Envelope, not [http://schemas.xmlsoap.org/soap/envelope/]Envelope. Error code App:19060
Error: Systeemmelding XML Type error (6EDB::4844)
element start ("SOAP-ENV:Envelope") rejected at 1, 240
Error code App:19060
Generic XML Import IMPL (6EDB::11267)
Generic XML Import (6EDB::9780)</soapenv12:Text>
I tried various examples like: Overwrite the Soap Envelope in Suds python
but they all add another namespace and do not seem to work. Any suggestions would be welcome.

python suds soap call Start and end tag names don't match

I'm a newb when it comes to soap, but here is what I have. If I make a soap call with perl's SOAP::Lite library, everything is cool. When I make the same call with suds, I get an error from the server.
Here is the working xml generated by the perl call:
<?xml version="1.0" encoding="UTF-8"?>
<soap:Envelope
soap:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:urn="urn:webservicesapi"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soap:Body>
<urn:getChassis xsi:nil="true" />
</soap:Body>
</soap:Envelope>
Making the same call with suds, I get this xml generated
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope
xmlns:ns0="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:ns1="urn:webservicesapi"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Header/>
<ns0:Body>
<ns1:getChassis/>
</ns0:Body>
</SOAP-ENV:Envelope>
The error produced with the server is: <ErrorCode>43</ErrorCode><Description>Start and end tag names don't match</Description>
If I use a soap plugin with my browser, I can replicate this. If I change the body to:
<SOAP-ENV:Body>
<urn:getChassis xsi:nil="true" />
</SOAP-ENV:Body>
The call works just fine.
So, I either need to know how to change the prefix for Body and urn: or I need to understand why the Start and end tag names don't match?
I understand I can use from suds.plugin import MessagePlugin to manipulate the xml before it is sent, but I am at a loss here.
Any help or advice would be greatly appreciated.
OK. Got it to work.
class EnvelopeFixer(MessagePlugin):
def marshalled(self, context):
context.envelope.getChild('ns0:Body').setPrefix('ns1')
Then I called the plugin when creating the client object
client = Client(WSDL_LOCATION, transport=t, location=url, plugins=[EnvelopeFixer()])

Python to read wsdl not working

I am trying this code to fetch data from wsdl.
Querying the website for the zipid("60630") works fine but in my code it gives the error as
"Invalid ZIP"
wsdlFile = 'http://wsf.cdyne.com/WeatherWS/Weather.asmx?wsdl'
wsdlObject = WSDL.Proxy(wsdlFile)
wsdlObject.show_methods()
zipid = "60630"
result = wsdlObject.GetCityWeatherByZIP(ZIP=zipid)
print result[1]
Can someone please help whats wrong here and why the code is not working correctly.
Thanks !!!
The problem probably is that your client sends a request the server doesn't understand. Seems you're using SOAPpy, that's the request it sends when I try it:
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope
SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance"
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsd="http://www.w3.org/1999/XMLSchema"
>
<SOAP-ENV:Body>
<GetCityWeatherByZIP SOAP-ENC:root="1">
<v1 xsi:type="xsd:string">60630</v1>
</GetCityWeatherByZIP>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
In comprison when using suds:
from suds.client import Client
cli = Client("http://wsf.cdyne.com/WeatherWS/Weather.asmx?wsdl")
cli.service.GetCityWeatherByZIP(ZIP=60630)
it produces:
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:ns0="http://ws.cdyne.com/WeatherWS/"
xmlns:ns1="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Header/>
<ns1:Body>
<ns0:GetCityWeatherByZIP>
<ns0:ZIP>60630</ns0:ZIP>
</ns0:GetCityWeatherByZIP>
</ns1:Body>
</SOAP-ENV:Envelope>
(captured using wireshark)
The second request returns a valid result from the server.
I don't know SOAPpy well enough to suggest a way to fix this, but maybe you could consider switching your client library to suds.

How to add header while making soap request using soappy

I have WSDL file, using that i wanted to make soap request which will look exactly like this --
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Header>
<AuthSoapHd xmlns="http://foobar.org/">
<strUserName>string</strUserName>
<strPassword>string</strPassword>
</AuthSoapHd>
</soap:Header>
<soap:Body>
<SearchQuotes xmlns="http://foobar.org/">
<searchtxt>string</searchtxt>
</SearchQuotes>
</soap:Body>
</soap:Envelope>
To sovle this, i did this
>> from SOAPpy import WSDL
>> WSDLFILE = '/path/foo.wsdl'
>> server = WSDL.Proxy(WSDLFILE)
>> server.SearchQuotes('rel')
I get this error
faultType: <Fault soap:Server: System.Web.Services.Protocols.SoapException: Server was unable to process request. ---> System.NullReferenceException: Object reference not set to an instance of an object.
The i debugged it and got this
*** Outgoing SOAP ******************************************************
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope
SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance"
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsd="http://www.w3.org/1999/XMLSchema"
>
<SOAP-ENV:Body>
<SearchQuotes SOAP-ENC:root="1">
<v1 xsi:type="xsd:string">rel</v1>
</SearchQuotes>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
We can see it doesn't contain any header. I think that WSDL file has some bug.
Now, can anyone suggest me how to add header to this outgoing soap request.
Any sort of help will be appreciated. Thanks in advance
Not tested, but I believe you can use the method the docs suggest to add soap headers, i.e., make and prep a SOAPpy.Header instance, then use server = server._hd (hd) to get a proxy equipped with it (though in your case that does seem to be a workaround attempt to broken WSDL, as you say -- might it be better to fix the WSDL instead?).

Categories