Sending xml by SUDS - python

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})

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

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.

Modify suds request to target SOAP

I am having a problem with python suds trying to create a proper Suds XML Request:
This is my suds Code (after a few trials):
from suds import *
from suds.client import Client
from suds.transport.http import HttpAuthenticated
import logging
url = 'http://ws/webservices/600/ws.asmx?wsdl'
soap_client = Client(url, location='http://ws/webservices/600/ws.asmx')
soap_client.set_options(port='GatewayWebServiceSoap')
person = soap_client.factory.create('checkIfExists')
person.UserID = 'toni.tester#anywhere.at'
person.SessionID = ''
eventService = soap_client.service.CustomerService(person)
print 'last received:'
print soap_client.last_received()
print '-------------------------------------'
print 'last sent:'
print soap_client.last_sent()
This is what my suds sends:
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:ns0="http://service.example.at/gateway/v6.00" 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:Service>
<ns0:Service>
<ns0:SessionID></ns0:SessionID>
<ns0:UserID>toni.tester#anywhere.at</ns0:UserID>
</ns0:Service>
</ns0:Service>
</ns1:Body>
</SOAP-ENV:Envelope>
And this is what the WebService expects:
<?xml version="1.0" encoding="UTF-8"?>
<GATEWAY xmlns="urn:service-example-at:gateway:v4-00">
<Service>
<checkIfExists>
<SessionID></SessionID>
<UserID>test</UserID>
</checkIfExists>
</Service>
</GATEWAY>
My Questions:
How can I change SOAP-ENV:Envelope -> GATEWAY
How can I remove the namespaces ns1, ns0?
How can I remove the Body
If you really don't care about WSDL and stuff you can easily write request generator yourself since xml request is just a string template. That's what i did for my soapy needs.

SUDS loosing SOAP part of body

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.

Categories