sending a handmade SOAP request

Discussion in 'Python' started by Bernard, Jan 31, 2008.

  1. Bernard

    Bernard Guest

    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?
     
    Bernard, Jan 31, 2008
    #1
    1. Advertisements

  2. Bernard

    Van Gale Guest

    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.
     
    Van Gale, Jan 31, 2008
    #2
    1. Advertisements

  3. Stefan Behnel, Jan 31, 2008
    #3
  4. Bernard

    Bernard Guest

    oh my that is quite the handy answer Van Gal! I'll try it out right
    now. thanks a bunch man!
     
    Bernard, Jan 31, 2008
    #4
    1. Advertisements

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.