sending a handmade SOAP request


B

Bernard

Hey y'all,

Is there a way to POST a handmade SOAP request *without* using any
libraries like SOAPpy? I've been having some communication trouble
with a server using the new wse3 (http://www.microsoft.com/Downloads/
details.aspx?
familyid=018A09FD-3A74-43C5-8EC1-8D789091255D&displaylang=en).

they keep on sending back this strange error :
SOAPpy.Types.faultType: <Fault q0:Security: Header
http://schemas.xmlsoap.org/ws/2004/08/addressing:Action for ultimate
recipient is required but not present in the message.>

We've tried using SOAPui (http://sourceforge.net/projects/soapui/) as
well to test the web service out. this little baby builds a proper
SOAP request based on the wsdl file. we keep on hitting that error
again & again...

so what is up with that?
 
Ad

Advertisements

V

Van Gale

Hey y'all,

Is there a way to POST a handmade SOAP request *without* using any
libraries like SOAPpy?

Yes, it's quite easy to SOAP by hand.

I use Oren Tirosh's ElementBuilder class (on top of lxml instead of
ElementTree) to build the SOAP request and the xpath capabilities in lxml
to pull out the data I need from the response.

http://www.tothink.com/python/ElementBuilder/
http://codespeak.net/lxml/

An incomplete example for contructing a request looks something like this:

body = Element('soap:Envelope',
{ 'xmlns:soap': nss['soap']},
Element('soap:Header'), Element('soap:Body',
{ 'xmlns:msgs': nss['msgs'] },
Element('msgs:login',
Element('msgs:passport',
{ 'xmlns:core': nss['core'] },
Element('core:password', password),
Element('core:account', account)))))

I use httplib2 for sending the HTTP requests:

http://code.google.com/p/httplib2/

Incomplete example:

headers['SOAPAction'] = action
headers['Content-length'] = str(len(etree.tostring(body)))
response, content = self._client.request(
self.ns_uri, "POST",
body=etree.tostring(body), headers=self._headers)
if response.status == 500 and not \
(response["content-type"].startswith("text/xml") and \
len(content) > 0):
raise HTTPError(response.status, content)
if response.status not in (200, 500):
raise HTTPError(response.status, content)
doc = etree.parse(StringIO(content))
if response.status == 500:
faultstring = doc.findtext(".//faultstring")
raise HTTPError(response.status, faultstring)

Now it's just a matter of using xpath expressions to dig into the "doc"
structure for the bits you need.
 
S

Stefan Behnel

Ad

Advertisements

B

Bernard

Yes, it's quite easy to SOAP by hand.

I use Oren Tirosh's ElementBuilder class (on top of lxml instead of
ElementTree) to build the SOAP request and the xpath capabilities in lxml
to pull out the data I need from the response.

http://www.tothink.com/python/ElementBuilder/http://codespeak.net/lxml/

An incomplete example for contructing a request looks something like this:

body = Element('soap:Envelope',
{ 'xmlns:soap': nss['soap']},
Element('soap:Header'), Element('soap:Body',
{ 'xmlns:msgs': nss['msgs'] },
Element('msgs:login',
Element('msgs:passport',
{ 'xmlns:core': nss['core'] },
Element('core:password', password),
Element('core:account', account)))))

I use httplib2 for sending the HTTP requests:

http://code.google.com/p/httplib2/

Incomplete example:

headers['SOAPAction'] = action
headers['Content-length'] = str(len(etree.tostring(body)))
response, content = self._client.request(
self.ns_uri, "POST",
body=etree.tostring(body), headers=self._headers)
if response.status == 500 and not \
(response["content-type"].startswith("text/xml") and \
len(content) > 0):
raise HTTPError(response.status, content)
if response.status not in (200, 500):
raise HTTPError(response.status, content)
doc = etree.parse(StringIO(content))
if response.status == 500:
faultstring = doc.findtext(".//faultstring")
raise HTTPError(response.status, faultstring)

Now it's just a matter of using xpath expressions to dig into the "doc"
structure for the bits you need.

oh my that is quite the handy answer Van Gal! I'll try it out right
now. thanks a bunch man!
 

Top