My favorites | Sign in
Project Home Downloads Wiki Issues Source
Search
for
SoapServer  
Minimal standalone server implementation
Featured, Phase-Support
Updated Sep 26, 2010 by reingart

SOAP Server

SoapDispatcher is intended to be used from web frameworks (see Web2Py) to expose webservice functionalities.

Although, a minimal HTTP server is included to test basic features or show how to embed it other applications if no web framework is available.

For testing, SOAPHandler (a minimal BaseHTTPRequestHandler implementation) can be used. Following is some sample code.

WARNING: current release (experimental) of this server is in alpha status, not intended to be used in production by now.

Example

This example expose an adder function that receive two integers and returns his sum.

Basic instrospection information about the webservice can be seen using a browser:

For a nicer webpage with complete method help and esy interface, see Web2Py implementation.

Server

Python's built-in HTTPServer can be used with SOAPHandler to expose a minimal SOAP Server:

from pysimplesoap.server import SoapDispatcher, SOAPHandler
from BaseHTTPServer import HTTPServer

def adder(a,b):
    "Add two values"
    return a+b

dispatcher = SoapDispatcher(
    'my_dispatcher',
    location = "http://localhost:8008/",
    action = 'http://localhost:8008/', # SOAPAction
    namespace = "http://example.com/sample.wsdl", prefix="ns0",
    trace = True,
    ns = True)

# register the user function
dispatcher.register_function('Adder', adder,
    returns={'AddResult': int}, 
    args={'a': int,'b': int})

print "Starting server..."
httpd = HTTPServer(("", 8008), SOAPHandler)
httpd.dispatcher = dispatcher
httpd.serve_forever()

Client

To test this minimal server, a minimal client can be used:

from pysimplesoap.client import SoapClient, SoapFault

# create a simple consumer
client = SoapClient(
    location = "http://localhost:8008/",
    action = 'http://localhost:8008/', # SOAPAction
    namespace = "http://example.com/sample.wsdl", 
    soap_ns='soap',
    trace = True,
    ns = False)

# call the remote method
response = client.Adder(a=1, b=2)

# extract and convert the returned value
result = response.AddResult
print int(result)

The expected output should be:

--------------------------------------------------------------------------------
POST http://localhost:8008/
SOAPAction: "http://localhost:8008/Adder"
Content-length: 329
Content-type: text/xml; charset="UTF-8"

<?xml version="1.0" encoding="UTF-8"?><soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soap:Body>
    <Adder xmlns="http://example.com/sample.wsdl">
    <a>1</a><b>2</b></Adder>
</soap:Body>
</soap:Envelope>

date: Tue, 20 Jul 2010 23:39:21 GMT
status: 200
content-type: text/xml
server: BaseHTTP/0.3 Python/2.5.4
<?xml version="1.0" encoding="UTF-8"?><soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body><AdderResponse xmlns="http://example.com/sample.wsdl"><AddResult>3</AddResult></AdderResponse></soap:Body>
</soap:Envelope>
================================================================================
3
Comment by jphthier...@gmail.com, Sep 1, 2010

Hi,

I am new to soap with Python; your work sounds very interesting:

easy to use good compatibility with other clients compact code :-)

Small typo in this example: the name arg is missing for the dispatcher. One question: I looked at the example in the source code (server.py); you use a list of dicts here. Is there another way to deal with arrays?

Comment by project member reingart, Sep 1, 2010

Thanks for your comment,

Sorry but I cannot find the typo, can you fill an Issue?

About arrays, yes, they are converted to lists. If you need something special, you can use raw SimpleXMLElement objects. BTW, if you want, we can discuss this at the Python Soap List: http://mail.python.org/mailman/listinfo/soap

Comment by mbertol...@gmail.com, Oct 13, 2010

Hello, I would like to know what return types can be retrieved to the client (in this case i can see that you use int and str).

Thanks, Martin

Comment by project member reingart, Oct 13, 2010

Martin: supported types are: {str:'string',unicode:'string', bool:'boolean', short:'short', byte:'byte', int:'int', long:'long', integer:'integer', float:'float', double:'double', Decimal:'decimal', datetime.datetime:'dateTime', datetime.date:'date'}, and using lists and dicts you can return more complex objects.

Some types are aliases for python ones, you can look at the code for more details: http://code.google.com/p/pysimplesoap/source/browse/simplexml.py#54

Comment by gill.te...@gmail.com, Jan 20, 2011

Can you please provide an example to stop the server too? I am doing following but port(8008) is never released.

class configurationServer(threading.Thread):

    def __init__(self):        
        self.server = None
        self.dispatcher = None
        self.config = None
        threading.Thread.__init__(self)

    def run(self): 
            self.dispatcher = SoapDispatcher(
                               'my_dispatcher',
                               location = "http://localhost:8008/",
                               action = 'http://localhost:8008/', # SOAPAction
                               namespace = "http://example.com/sample.wsdl", 
                               trace = True,
                               ns = True)
                      
            self.server = HTTPServer(("",8008),SOAPHandler)
            self.server.dispatcher = self.dispatcher
            self.server.serve_forever()

    def stop(self):
        self.server.shutdown()
        self.server.server_close()

My main class is calling start() and stop() on this thread.

Comment by project member reingart, Jan 21, 2011

gill.teena: Can you please fill an issue?

I don't fully understand you problem, but I think you have a multi-threading issue here, serve_forever() should block and create new threads out of your control, you should have to look at: http://docs.python.org/library/basehttpserver.html#more-examples for a server that doesn't run forever.

Comment by luen...@gmail.com, Apr 18, 2011

Please I using python 3 and not work the library SOAP, please help!

Comment by maurizio.totti, May 19, 2011

Hi, have you done anything about WS-Security functions? Regards

Comment by nico.pre...@gmail.com, Feb 19, 2012

I always receive the following error when I try to call the function mentioned above (response = client.Adder(a=1, b=2)):

Traceback (most recent call last):
  File "SOAPClient.py", line 10, in <module>
    ns = True)
  File "/Users/Nico/Development/Python/PackagePrototype/test/client.py", line 103, in __init__
    self.http = Http(timeout=TIMEOUT, cacert=cacert, proxy=proxy, sessions=sessions)
  File "/Users/Nico/Development/Python/PackagePrototype/test/transport.py", line 88, in __init__
    raise RuntimeError('timeout is not supported with urllib2 transport')
RuntimeError: timeout is not supported with urllib2 transport

I have a 1:1 copy of the client and server code above. Starting the server first and calling the registered function. The server seems to start OK, with no errors.

Please help, thanks!

Comment by nico.pre...@gmail.com, Feb 20, 2012

Oke, fixed it. I had to change the variable timeout from 60 to None in the module client. Now it works fine!


Sign in to add a comment
Powered by Google Project Hosting