SUDS loosing SOAP part of body - python

I'm sending a SOAP request to update some entity. When I create (instead of update) nearly same thing, everything works fine. I've tracked logging from Client and Transport and finally it gave me a clue. It looks like this:
DEBUG:suds.client:sending to (https://webservices.autotask.net/ATServices/1.5/atws.asmx)
message:
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:ns0="http://autotask.net/ATWS/v1_5/" 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:update>
<ns0:Entities xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<ns0:Entity xsi:type="ns0:Ticket">
<ns0:id>123</ns0:id>
<ns0:UserDefinedFields xsi:type="xsd:string"></ns0:UserDefinedFields>
<ns0:AccountID xsi:type="xsd:string">123</ns0:AccountID>
<ns0:AllocationCodeID xsi:type="xsd:string">123</ns0:AllocationCodeID>
<ns0:CompletedDate xsi:type="xsd:string">2011-04-04 14:47:02</ns0:CompletedDate>
<ns0:CreateDate xsi:type="xsd:string">2011-04-04 04:08:02.000203</ns0:CreateDate>
<ns0:CreatorResourceID xsi:type="xsd:string">123</ns0:CreatorResourceID>
<ns0:Description xsi:type="xsd:string"></ns0:Description>
<ns0:DueDateTime xsi:type="xsd:string">2011-04-05 09:36:00</ns0:DueDateTime>
<ns0:EstimatedHours xsi:type="xsd:string">0.0</ns0:EstimatedHours>
<ns0:IssueType xsi:type="xsd:string">123</ns0:IssueType>
<ns0:LastActivityDate xsi:type="xsd:string">2011-04-04 14:47:04.000157</ns0:LastActivityDate>
<ns0:Priority xsi:type="xsd:string">123</ns0:Priority>
<ns0:QueueID xsi:type="xsd:string">123</ns0:QueueID>
<ns0:Status xsi:type="xsd:string">123</ns0:Status>
<ns0:SubIssueType xsi:type="xsd:string">123</ns0:SubIssueType>
<ns0:TicketNumber xsi:type="xsd:string">123</ns0:TicketNumber>
<ns0:Title xsi:type="xsd:string">foo</ns0:Title>
<ns0:FirstResponseDateTime xsi:type="xsd:string">2011-04-04 14:47:02.000427</ns0:FirstResponseDateTime>
<ns0:ResolutionPlanDateTime xsi:type="xsd:string">2011-04-04 14:47:02.000427</ns0:ResolutionPlanDateTime>
<ns0:ResolvedDateTime xsi:type="xsd:string">2011-04-04 14:47:02.000427</ns0:ResolvedDateTime>
<ns0:Resolution xsi:type="xsd:string"></ns0:Resolution>
</ns0:Entity>
</ns0:Entities>
</ns0:update>
</ns1:Body>
</SOAP-ENV:Envelope>
DEBUG:suds.client:headers = {'SOAPAction': u'"http://autotask.net/ATWS/v1_5/update"';, 'Content-Type': 'text/xml; charset=utf-8'}
DEBUG:suds.transport.http:sending:
URL:https://webservices.autotask.net/ATServices/1.5/atws.asmx
HEADERS: {'Soapaction': u'"http://autotask.net/ATWS/v1_5/update"', 'SOAPAction': u'"http://autotask.net/ATWS/v1_5/update"', 'Content-Type': 'text/xml; charset=utf-8', 'Content-type': 'text/xml; charset=utf-8', 'Authorization': 'Basic YXV0b21hdGlhQGFyY2VzLm5ldDp5dWYkOWFyN2VQaDY='}
MESSAGE:
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:ns0="http://autotask.net/ATWS/v1_5/" 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:update>
<Entities/>
</ns0:update>
</ns1:Body>
</SOAP-ENV:Envelope>
And with this I get an error:
Object reference not set to an instance of an object.
Anyone has any idea, what happens with this SOAP request, that it looses it's whole Entity body and proceed an empty message? Is it a problem with suds, server, code, me?
Thanks for any little help in understing what's happening.

I'm answering my own question, so I can finally close it.
If anyone will be interested, the problem was solved. There is a bug in suds.sx reported here. As the SOAP request was edited with this one, the request which I sent was empty. To correct it, I had to delete the sx part and change it with a MessagePlugin. If anyone will be interested - write here.

Related

Creating soap request with suds

I need some help with suds request in python.
Generated XML request looks like this
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<SOAP-ENV:Header>
<m:ExternalApiHeader xmlns:m="http://www.GlobalBettingExchange.com/ExternalAPI/" version="" languageCode="" username="" password="" applicationIdentifier=""/>
</SOAP-ENV:Header>
<SOAP-ENV:Body>
<m:GetEventSubTreeWithSelections xmlns:m="http://www.GlobalBettingExchange.com/ExternalAPI/">
<m:getEventSubTreeWithSelectionsRequest WantPlayMarkets="true">
<m:EventClassifierIds>2147483647</m:EventClassifierIds>
</m:getEventSubTreeWithSelectionsRequest>
</m:GetEventSubTreeWithSelections>
</SOAP-ENV:Body>
I have created python script and the only thing I can't figure out how to pass the value EventClassifierIds, which is 2147483647
import suds
url = 'http://api.betdaq.com/v2.0/API.wsdl'
client = suds.client.Client(url)
#prepare headers
token=client.factory.create('ExternalApiHeader')
token._version='2'
token._languageCode='en'
token._username=''
token._password=''
client.set_options(soapheaders=token)
#reguest
result = client.service.GetEventSubTreeWithSelections('false')
print result

Sending xml by SUDS

I would like to send my hand build xml by SUDS using WSDL. I found, that I can do it like that:
xml = Raw("""
<SOAP-ENV:Envelope xmlns:ns0="urn:ca:std:cdc:tech:xsd:cdc.001.01" 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:GetAccountBalance>
<ns0:Document>
<myData>
something
</myData>
</ns0:Document>
</ns0:GetAccountBalance>
</ns1:Body>
</SOAP-ENV:Envelope>
""")
print client.service.GetAccountBalance(xml)
But using this method SUDS sends:
<SOAP-ENV:Envelope xmlns:ns0="urn:ca:std:cdc:tech:xsd:cdc.001.01" 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:GetAccountBalance>
<ns0:Document>
<SOAP-ENV:Envelope xmlns:ns0="urn:ca:std:cdc:tech:xsd:cdc.001.01" 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:GetAccountBalance>
<ns0:Document>
<myData>
something
</myData>
</ns0:Document>
</ns0:GetAccountBalance>
</ns1:Body>
</SOAP-ENV:Envelope>
</ns0:Document>
</ns0:GetAccountBalance>
</ns1:Body>
</SOAP-ENV:Envelope>
My question is, how can I send my XML, without adding anything by SUDS?
According to the suds documentation, you can send a raw SOAP message using the __inject argument to the method you're calling:
client.service.GetAccountBalance(__inject={'msg': xml})

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 do I add a factory created type as a header in suds?

I can't seem to get suds working with my setup. I have to pass a context, with a remote user set before I can use any of the functions in the API. What I tried to do was this:
client = Client(url, username=userid, password=password)
apiContext = client.factory.create("apiCallContext") # This is listed in the types
apiContext.remoteUser = "serviceAccount" # when I print the client
client.set_options(soapheaders=apiContext)
client.service.getActiveIPs()
Throughout the process, everything seems to be getting created correctly (if I print the client, I see all the functions and types, if I print apiContext, I see everything set correctly), but the headers don't actually seem to be getting set:
...
DEBUG:suds.client:sending to ($URL) message:
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:ns0=$NS
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:getActiveIPs/>
</ns1:Body>
</SOAP-ENV:Envelope>
DEBUG:suds.client:headers = {'SOAPAction': u'""',
'Content-Type': 'text/xml; charset=utf-8'}
DEBUG:suds.transport.http:sending:
URL:$URL
HEADERS: {'SOAPAction': u'""', 'Content-Type': 'text/xml; charset=utf-8',
'Content-type': 'text/xml; charset=utf-8', 'Soapaction': u'""'}
...
I'm not seeing the context anywhere in the headers, and the server is erroring out that there's no remote user set.
What am I doing wrong?
Without knowing the exact spec of the webservice you are working with, I can only hazard a guess at this answer, but the header looks similar to a web service I have used in the past. Have you tried creating the elements directly and passing them into the header thus?:
from suds.sax.element import Element
...
NS = ('h', SOME_NAMESPACE)
apiContext = Element('apiContext')
authcred = Element('authenticationCredential', ns=NS)
username = Element(userid, ns=NS).setText('USERNAME')
passw = Element(password, ns=NS).setText('PASSWORD')
authcred.append(username)
authcred.append(passw)
apiContext.append(authcred)
client.set_options(soapheaders=apiContext)
i.e. is the authentication part of the context object?

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