Sending SOAP request using Python Requests

PythonSoapPython Requests

Python Problem Overview


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

Python Solutions


Solution 1 - Python

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:

Solution 2 - Python

Adding up to the last answer, make sure you add to the headers the following attributes:

headers={"Authorization": f"bearer {token}", "SOAPAction": "http://..."}

The authorization is meant when you need some token to access the SOAP API,

Otherwise, the SOAPAction is the action you are going to perform with the data you are sending in,

So if you don't need Authorization, then you could pop that out of the headers,

That worked pretty fine for me,

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionDeepankar BajpeyiView Question on Stackoverflow
Solution 1 - Pythontoast38cozaView Answer on Stackoverflow
Solution 2 - PythonJesus PerezView Answer on Stackoverflow