In the last couple of years, it seems like webservices have become more and more the standard for sharing data with multiple applications. System designers and architects are pushing back against the idea of connecting directly to a database to access data. Instead, they prefer applications to access data through a middle-ware solution such as webservices.
Most current programming languages have the ability call webservices as long as they can parse XML. Typically when one needs to call a webservice, they would use an already written and proven library to do the work for them. After all, why reinvent the wheel? But, what about technologies that don’t have an existing library for calling webservices? Or, what about those who want to create their own webservice libraries?
Well, I want to take a minute to show you a really simple way to call webservices with Python using a standard HTTP post. I recently needed something quick for testing a webservice I wrote in another language and want to share that with you now. However, I won’t be showing you how to to parse the response XML in this article. I’ll save that for another post. But, with this simple approach to calling webservices, you’ll be able to send a SOAP message to a webservice and get back the response XML as a string. At that point, you can search Google for hundreds or even thousands of other sites that will show you how to parse the returned string as XML, or you can wait until I have time to write the second piece to this article. Let’s get started.
First off, all webservices that use the SOAP protocol expect what’s called a “SOAP envelope” to be passed to the service. The SOAP envelope is a simple XML structure that contains parameters that the webservice will be expecting. For this example, I have constructed a simple SOAP envelope that contains parameters for username and password. The webservice we’ll be calling is expecting these parameters for authentication purposes. Once the credentials have been authenticated, the webservice will simply return a list of other available services the host has to offer. Here is what my SOAP envelope looks like:
body = “””
<soapenv:Envelope xmlns:soapenv=”http://schemas.xmlsoap.org/soap/envelope/” xmlns:ns=”http://www.example.com/services/wsdl/2.0″>
</soapenv:Envelope>””” % (“username”, “password”)
Make sure you change the namespace URI (xmlns:ns=) in the envelope to match the namespace used in your webservice. You’ll also notice that I have added my username and password parameters to the end of my request body. For the purpose of this example, I have replaced my URLs and credentials with dummy data. So, make sure you change your parameters and URLs to match those of your webservice.
Next, you will need to construct the webservice request. For that, you can use the httplib class that comes with Python. Make sure you include an import for it at the top of your page. Then, build a “put” request and header as shown below. I’m not going to explain everything going on here as it’s pretty much self-explanatory. It’s just a standard HTTP POST like you would do from an HTML page.
request = httplib.HTTPConnection(server_addr)
request.putheader(“Accept”, “application/soap+xml, application/dime, multipart/related, text/*”)
request.putheader(“Content-Type”, “text/xml; charset=utf-8″)
request.putheader(“SOAPAction”, “http://” + server_addr + service_action)
That’s it. That’s everything you need to call a webservice using SOAP and Python. The only thing you have left to do is submit your request and print the response. If you are submitting data to a webservice and not expecting a response (a fire-and-forget if you will), this code will work perfectly for you. As mentioned earlier, in a future article I will show you how to parse the response as XML instead of one giant string as it is right now. Here is all of the code I used for this example. As always, leave your questions and comments in the comments section below.
import string, os, sys, httplib server_addr = "www.example.com" service_action = "/services/getServiceListAction" body = """ <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns="http://www.example.com/services/wsdl/2.0"> <soapenv:Header/> <soapenv:Body> <ns:serviceListRequest> <ns:userInfo> <ns:username>%s</ns:username> <ns:password>%s</ns:password> </ns:userInfo> </ns:serviceListRequest> </soapenv:Body> </soapenv:Envelope>""" % ("username", "password") request = httplib.HTTPConnection(server_addr) request.putrequest("POST", service_action) request.putheader("Accept", "application/soap+xml, application/dime, multipart/related, text/*") request.putheader("Content-Type", "text/xml; charset=utf-8") request.putheader("Cache-Control", "no-cache") request.putheader("Pragma", "no-cache") request.putheader("SOAPAction", "http://" + server_addr + service_action) request.putheader("Content-Length", str(len(body))) request.endheaders() request.send(body) response = request.getresponse().read() print response