Ответ 1

ссылка: (Спасибо Дугу Хеллманну) здание мыла

Инфраструктура Zolera Soap (ZSI), является частью проекта pywebsvcs. Он предоставляет полные серверные и клиентские библиотеки для работы с SOAP. Чтобы использовать его, разработчик записывает файл WSDL (вручную или с помощью редактора WSDL), а затем генерирует источник Python для клиента и заглушки для сервера. Структуры данных, определенные в файле WSDL, преобразуются в классы Python, которые могут использоваться как в клиентском, так и в сервере.

мы внедрили простую службу эха, которая возвращает в качестве вывода все, что получает от клиента. Листинг 1 содержит входы WSDL, созданные вручную, для версии этой службы ZSI.

Листинг 1

<?xml version="1.0" encoding="UTF-8"?>
<definitions 
  xmlns="http://schemas.xmlsoap.org/wsdl/"
  xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
  xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
  xmlns:http="http://schemas.xmlsoap.org/wsdl/http/"
  xmlns:xsd="http://www.w3.org/2001/XMLSchema"
  xmlns:tns="urn:ZSI"
  targetNamespace="urn:ZSI" >

  <types>
    <xsd:schema elementFormDefault="qualified" 
        targetNamespace="urn:ZSI">
      <xsd:element name="Echo">
        <xsd:complexType>
          <xsd:sequence>
            <xsd:element name="value" type="xsd:anyType"/>
          </xsd:sequence>
        </xsd:complexType>
      </xsd:element>
    </xsd:schema>
  </types>

  <message name="EchoRequest">
    <part name="parameters" element="tns:Echo" />
  </message>
  <message name="EchoResponse">
    <part name="parameters" element="tns:Echo"/>
  </message>

  <portType name="EchoServer">
    <operation name="Echo">
      <input message="tns:EchoRequest"/>
      <output message="tns:EchoResponse"/>
    </operation>
  </portType>

  <binding name="EchoServer" type="tns:EchoServer">
    <soap:binding style="document" 
                  transport="http://schemas.xmlsoap.org/soap/http"/>
    <operation name="Echo">
      <soap:operation soapAction="Echo"/>
      <input>
        <soap:body use="literal"/> 
      </input>
      <output>
        <soap:body use="literal"/> 
      </output>
    </operation>
  </binding>

  <service name="EchoServer">
    <port name="EchoServer" binding="tns:EchoServer">
      <soap:address location="http://localhost:7000"/>
    </port>
  </service>

</definitions>

Чтобы сгенерировать код клиента и сервера из WSDL, подайте его в программу wsdl2py (включенную в ZSI). Чтобы добавить поддержку сложных типов, добавьте параметр -b, но это не обязательно для этого простого примера. wsdl2py, в ответ, создаст три файла:

Листинг 2

EchoServer_client.py - это код, необходимый для создания клиента для веб-службы SimpleEcho.

##################################################
# file: EchoServer_client.py
# 
# client stubs generated by 
# "ZSI.generate.wsdl2python.WriteServiceModule"
# 
##################################################

from EchoServer_types import *
import urlparse, types
from ZSI.TCcompound import ComplexType, Struct
from ZSI import client
from ZSI.schema import GED, GTD
import ZSI
from ZSI.generate.pyclass import pyclass_type

# Locator
class EchoServerLocator:
    EchoServer_address = "http://localhost:7000"
    def getEchoServerAddress(self):
        return EchoServerLocator.EchoServer_address
    def getEchoServer(self, url=None, **kw):
        return EchoServerSOAP(
            url or EchoServerLocator.EchoServer_address, 
            **kw)

# Methods
class EchoServerSOAP:
    def __init__(self, url, **kw):
        kw.setdefault("readerclass", None)
        kw.setdefault("writerclass", None)
        # no resource properties
        self.binding = client.Binding(url=url, **kw)
        # no ws-addressing

    # op: Echo
    def Echo(self, request, **kw):
        if isinstance(request, EchoRequest) is False:
            raise TypeError, "%s incorrect request type" % \
                (request.__class__)
        # no input wsaction
        self.binding.Send(None, None, request, soapaction="Echo", **kw)
        # no output wsaction
        response = self.binding.Receive(EchoResponse.typecode)
        return response

EchoRequest = GED("urn:ZSI", "Echo").pyclass

EchoResponse = GED("urn:ZSI", "Echo").pyclass

Листинг 3

EchoServer_server.py содержит код, необходимый для создания сервера веб-сервисов SimpleEcho.

##################################################
# file: EchoServer_server.py
#
# skeleton generated by 
#  "ZSI.generate.wsdl2dispatch.ServiceModuleWriter"
#
##################################################

from ZSI.schema import GED, GTD
from ZSI.TCcompound import ComplexType, Struct
from EchoServer_types import *
from ZSI.ServiceContainer import ServiceSOAPBinding

# Messages  
EchoRequest = GED("urn:ZSI", "Echo").pyclass

EchoResponse = GED("urn:ZSI", "Echo").pyclass


# Service Skeletons
class EchoServer(ServiceSOAPBinding):
    soapAction = {}
    root = {}

    def __init__(self, post='', **kw):
        ServiceSOAPBinding.__init__(self, post)

    def soap_Echo(self, ps, **kw):
        request = ps.Parse(EchoRequest.typecode)
        return request,EchoResponse()

    soapAction['Echo'] = 'soap_Echo'
    root[(EchoRequest.typecode.nspname,EchoRequest.typecode.pname)] = \
        'soap_Echo'

Листинг 4

EchoServer_types.py имеет определения типов, используемые как кодом клиента, так и сервером.

##################################################
# file: EchoServer_types.py
#
# schema types generated by 
#  "ZSI.generate.wsdl2python.WriteServiceModule"
#
##################################################

import ZSI
import ZSI.TCcompound
from ZSI.schema import (LocalElementDeclaration, ElementDeclaration, 
                        TypeDefinition, GTD, GED)
from ZSI.generate.pyclass import pyclass_type

##############################
# targetNamespace
# urn:ZSI
##############################

class ns0:
    targetNamespace = "urn:ZSI"

    class Echo_Dec(ZSI.TCcompound.ComplexType, ElementDeclaration):
        literal = "Echo"
        schema = "urn:ZSI"
        def __init__(self, **kw):
            ns = ns0.Echo_Dec.schema
            TClist = [ZSI.TC.AnyType(pname=(ns,"value"), 
                      aname="_value", minOccurs=1, maxOccurs=1, 
                      nillable=False, typed=False, 
                      encoded=kw.get("encoded"))]
            kw["pname"] = ("urn:ZSI","Echo")
            kw["aname"] = "_Echo"
            self.attribute_typecode_dict = {}
            ZSI.TCcompound.ComplexType.__init__(self,None,TClist,
                                                inorder=0,**kw)
            class Holder:
                __metaclass__ = pyclass_type
                typecode = self
                def __init__(self):
                    # pyclass
                    self._value = None
                    return
            Holder.__name__ = "Echo_Holder"
            self.pyclass = Holder

# end class ns0 (tns: urn:ZSI)

После создания эти файлы не предназначены для редактирования, потому что они будут восстановлены как часть процесса сборки всякий раз, когда изменяется вход WSDL. Код в файлах растет, так как к определению службы добавляются все больше типов и вызовов.

Реализация сервера идет в отдельный файл, который импортирует сгенерированный код. В примере фактический сервис находится в строках 18-25 листинга 5. Декодер @soapmethod определяет вход (EchoRequest) и вывод (EchoResponse) для вызова. В примере реализация soap_Echo() просто заполняет значение ответа значением запроса и возвращает как запрос, так и ответ. Оттуда ZSI заботится о создании ответа SOAP и отправке его клиенту.

Листинг 5

import os
import sys
from EchoServer_client import *
from ZSI.twisted.wsgi import (SOAPApplication,
                              soapmethod,
                              SOAPHandlerChainFactory)

class EchoService(SOAPApplication):
    factory = SOAPHandlerChainFactory
    wsdl_content = dict(name='Echo', 
                        targetNamespace='urn:echo', 
                        imports=(), 
                        portType='',
                        )

    def __call__(self, env, start_response):
        self.env = env
        return SOAPApplication.__call__(self, env, start_response)

    @soapmethod(EchoRequest.typecode, 
                EchoResponse.typecode, 
                operation='Echo', 
                soapaction='Echo')
    def soap_Echo(self, request, response, **kw):
        # Just return what was sent
        response.Value = request.Value
        return request, response

def main():
    from wsgiref.simple_server import make_server
    from ZSI.twisted.wsgi import WSGIApplication

    application         = WSGIApplication()
    httpd               = make_server('', 7000, application)
    application['echo'] = EchoService()
    print "listening..."
    httpd.serve_forever()

if __name__ == '__main__':
    main()

В листинге 6 приведен пример использования клиентских библиотек ZSI для доступа к серверам с конца клиента. Все, что нужно сделать, это создать дескриптор веб-службы EchoServer, создать EchoRequest, отправить его в веб-службу и прочитать ответ.

from EchoServer_client import *
import sys, time

loc  = EchoServerLocator()
port = loc.getEchoServer(url='http://localhost:7000/echo')

print "Echo: ", 
msg = EchoRequest()
msg.Value = "Is there an echo in here?"
rsp = port.Echo(msg)
print rsp.Value