Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sending SOAP request using Python Requests

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

like image 291
Deepankar Bajpeyi Avatar asked Aug 11 '13 18:08

Deepankar Bajpeyi


People also ask

How do you do a SOAP request in Python?

To make SOAP requests to the SOAP API endpoint, use the "Content-Type: application/soap+xml" request header, which tells the server that the request body contains a SOAP envelope. The server informs the client that it has returned a SOAP envelope with a "Content-Type: application/soap+xml" response header.

Does Python support SOAP?

Python Web Services and Zolera Soap Infrastructure ((ZSI on PyPi) provides both client and server SOAP libraries.

How do you send a request in Python?

To create a POST request in Python, use the requests. post() method. The requests post() method accepts URL. data, json, and args as arguments and sends a POST request to a specified URL.


1 Answers

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:

  • SOAP Request with requests
  • SOAP Request with suds
like image 110
toast38coza Avatar answered Sep 21 '22 17:09

toast38coza