Sending SOAP request using Python Requests

Is it possible to use Python's requests library to send a SOAP request?

It is indeed possible.

Here is an example calling the Weather SOAP Service using plain requests lib:

    import requests
    url="http://wsf.cdyne.com/WeatherWS/Weather.asmx?WSDL"
    #headers = {'content-type': 'application/soap+xml'}
    headers = {'content-type': 'text/xml'}
    body = """<?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:GetWeatherInformation/></ns1:Body>
             </SOAP-ENV:Envelope>"""

    response = requests.post(url,data=body,headers=headers)
    print response.content

Some notes:

  • The headers are important. Most SOAP requests will not work without the correct headers. application/soap+xml is probably the more correct header to use (but the weatherservice prefers text/xml
  • This will return the response as a string of xml - you would then need to parse that xml.
  • For simplicity I have included the request as plain text. But best practise would be to store this as a template, then you can load it using jinja2 (for example) - and also pass in variables.

For example:

    from jinja2 import Environment, PackageLoader
    env = Environment(loader=PackageLoader('myapp', 'templates'))
    template = env.get_template('soaprequests/WeatherSericeRequest.xml')
    body = template.render()

Some people have mentioned the suds library. Suds is probably the more correct way to be interacting with SOAP, but I often find that it panics a little when you have WDSLs that are badly formed (which, TBH, is more likely than not when you're dealing with an institution that still uses SOAP ;) ).

You can do the above with suds like so:

    from suds.client import Client
    url="http://wsf.cdyne.com/WeatherWS/Weather.asmx?WSDL"
    client = Client(url)
    print client ## shows the details of this service

    result = client.service.GetWeatherInformation() 
    print result

Note: when using suds, you will almost always end up needing to use the doctor!

Finally, a little bonus for debugging SOAP; TCPdump is your friend. On Mac, you can run TCPdump like so:

    sudo tcpdump -As 0

This can be helpful for inspecting the requests that actually go over the wire.

The above two code snippets are also available as gists:

From: stackoverflow.com/q/18175489