djangosoapspyne

How can I create a basic Soap server with spyne in django


I want to create a server which uses Django and make and take response as SOAP, so I try to use spyne for this reason but I can't run the given code

class HelloWorldService(ServiceBase):
    @rpc(Unicode, Integer, _returns=Iterable(Unicode))
    def say_hello(ctx, name, times):
        """Docstrings for service methods appear as documentation in the wsdl.
        <b>What fun!</b>
        @param name the name to say hello to
        @param times the number of times to say hello
        @return the completed array
        """

        for i in range(times):
            yield u'Hello, %s' % name


application = Application([HelloWorldService], 'spyne.examples.hello.soap',
                          in_protocol=Soap11(validator='lxml'),
                          out_protocol=Soap11())

wsgi_application = WsgiApplication(application)


if __name__ == '__main__':
    import logging

    from wsgiref.simple_server import make_server

    logging.basicConfig(level=logging.DEBUG)
    logging.getLogger('spyne.protocol.xml').setLevel(logging.DEBUG)

    logging.info("listening to http://127.0.0.1:8000")
    logging.info("wsdl is at: http://localhost:8000/?wsdl")

    server = make_server('127.0.0.1', 8000, wsgi_application)
    server.serve_forever()

Solution

  • Remove validator='lxml' option in in_protocol

    I don't know the reason, the validator took a long time response or did not work.

    And add import statements

    from spyne import Application, rpc, ServiceBase, Iterable, Integer, Unicode
    
    from spyne.protocol.soap import Soap11
    from spyne.server.wsgi import WsgiApplication
    
    class HelloWorldService(ServiceBase):
        @rpc(Unicode, Integer, _returns=Iterable(Unicode))
        def say_hello(ctx, name, times):
            """Docstrings for service methods appear as documentation in the wsdl.
            <b>What fun!</b>
            @param name the name to say hello to
            @param times the number of times to say hello
            @return the completed array
            """
    
            for i in range(times):
                yield u'Hello, %s' % name
    
    
    application = Application([HelloWorldService], 'spyne.examples.hello.soap',
                    in_protocol=Soap11(),
                    out_protocol=Soap11())
    
    wsgi_application = WsgiApplication(application)
    
    if __name__ == '__main__':
        import logging
    
        from wsgiref.simple_server import make_server
    
        logging.basicConfig(level=logging.DEBUG)
        logging.getLogger('spyne.protocol.xml').setLevel(logging.DEBUG)
    
        logging.info("listening to http://127.0.0.1:8000")
        logging.info("wsdl is at: http://localhost:8000/?wsdl")
    
        server = make_server('127.0.0.1', 8000, wsgi_application)
        server.serve_forever()
    

    This is my test result by Postman and curl

    Body of POST commend

    <?xml version="1.0" encoding="utf-8"?>
    <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
      <soap:Body>
        <say_hello xmlns="spyne.examples.hello.soap">
            <name>Tom Cruise</name>
            <times>3</times>
        </say_hello>
      </soap:Body>
    </soap:Envelope>
    

    enter image description here

    curl POST commend with XML lint for terminal pipeline

    $ curl --location --request POST 'http://localhost:8000' --header 'Content-Type: text/xml; charset=utf-8' --header 'SOAPAction: say_hello' --data-raw '<?xml version="1.0" encoding="utf-8"?>
    <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
      <soap:Body>
        <say_hello xmlns="spyne.examples.hello.soap">
            <name>Tom Cruise</name>
            <times>3</times>
        </say_hello>
      </soap:Body>
    </soap:Envelope>
    ' | xmllint --format -
    
      % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                     Dload  Upload   Total   Spent    Left  Speed
    100   707  100   427  100   280   9319   6111 --:--:-- --:--:-- --:--:-- 15711
    <?xml version="1.0" encoding="UTF-8"?>
    <soap11env:Envelope xmlns:soap11env="http://schemas.xmlsoap.org/soap/envelope/" xmlns:tns="spyne.examples.hello.soap">
      <soap11env:Body>
        <tns:say_helloResponse>
          <tns:say_helloResult>
            <tns:string>Hello, Tom Cruise</tns:string>
            <tns:string>Hello, Tom Cruise</tns:string>
            <tns:string>Hello, Tom Cruise</tns:string>
          </tns:say_helloResult>
        </tns:say_helloResponse>
      </soap11env:Body>
    </soap11env:Envelope>
    

    And my python version and spyne version

    $ python --version
    Python 3.10.4
    
    $ pip show spyne
    Name: spyne
    Version: 2.14.0