Current

This document is valid for the current version of Plone.

simple SOAP client using Suds

by Duco Dokter last modified Apr 28, 2010 10:57 PM
This howto shows an easy way of creating a SOAP client for Plone, using the SOAP library Suds. The example is meant to provide a comparison with ZSI, as described in the howto "Importing a SOAP client object to be used by python scripts".

Yet another way of enabling SOAP calls from your Plone code.

Why would you want another way? Well, for one, the Suds way of doing SOAP calls is very elegant, needs very few lines of code, and uses the WSDL of the service for introspection and definitions, so as to save you from doing that. Also, the Suds library is well documented, and seems more lively than alternatives, like ZSI/SOAPpy. Enough reasons, I'd say.

The use case

Many websites out there offer webservices using SOAP. For integrating those services into your Plone site, you'll need to be able to do a SOAP call, or in other words, you'll need a SOAP client.

Setup

Add suds to either your global libraries, or to your buildout config file. I assume you know how to do this...

The code

Time to do some coding. We assume that we have a specific SOAP service, that has provided a WSDL file for introspection. Most, if not all serious SOAP services will be defined with an on-line WSD. We'll take the same service (Amazon) that is used in Importing a SOAP client object to be used by python scripts, so as to provide a clear comparison between suds and ZSI.

import suds
from suds.xsd.doctor import ImportDoctor, Import

WSDL_URL = "http://soap.amazon.com/schemas3/AmazonWebServices.wsdl"


class AmazonClient(object):


    def __init__(self):

        self._v_client = None


    def getClient(self):

        if not self._v_client:
            
            # Fix import for parsing this WSDL
            imp = Import('http://schemas.xmlsoap.org/soap/encoding/')
            d = ImportDoctor(imp)

            self._v_client = suds.client.Client(WSDL_URL, doctor=d)

        return self._v_client


    def extractByKeyword(self, keyword, mode, offset):

        """ fetch the calendar given the data provided by the user """

        client = self.getClient()

        req = client.factory.create("KeywordRequest")

        req.type='heavy'
        req.keyword=keyword
        req.mode=mode
        req.page=offset
        req.devtag='<your developer id>'
        req.tag='<your developer id>'

        return client.service.KeywordSearchRequest(req)

The relevant code for the actual request is in the definition of the extractByKeyword method. The code in the getClient method is more or less equivalent in function to the wsdl2py script, in that is sets up the client types, based on the WSDL. Note the fix for an import problem in suds...

In the extractByKeyword method, you can see how to create complex parameters, using the factory.create method of the client (that holds all WSDL definitions). The client that is returned from the getClient method can be printed, and provides a nice overview of the inspected WSDL. This is easiest done on the command line, like so:

>>> import suds
>>> from suds.xsd.doctor import ImportDoctor, Import
>>> imp = Import('http://schemas.xmlsoap.org/soap/encoding/')
>>> d = ImportDoctor(imp)
>>> url = "http://soap.amazon.com/schemas2/AmazonWebServices.wsdl"
>>> client = suds.client.Client(url, doctor=d)
>>> print client

This will display all available services declared in the WSDL, and all type info, so that you may know what type of parameters to create for what requests. The response object can similarly be printed from the command line, showing what is returned.

Filed under: ,

Contribute

Something wrong or out of date? Anybody can edit or create a new article in the knowledge base. Simply create an account on this site, log in, and click the Edit button to contribute.