2011-10-17 43 views

回答

10

參考:(感謝道格赫爾曼)building soap service

的Zolera皁基礎建設(ZSI),是pywebsvcs項目的一部分。它提供了完整的服務器和客戶端庫來處理SOAP。爲了使用它,開發人員編寫WSDL文件(手動或使用WSDL編輯器),然後爲客戶端生成Python源代碼併爲服務器生成存根。 WSDL文件中定義的數據結構被轉換爲可在客戶端和服務器代碼中使用的Python類。

我們實現了一個簡單的echo服務,該服務作爲輸出返回,無論它從客戶端獲得什麼輸入。清單1包含了該服務的ZSI版本的手工WSDL輸入。

清單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 Web服務所需的代碼。

################################################## 
# 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 Web服務的服務器所需的代碼。

################################################## 
# 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輸入的變化的一部分。隨着更多類型和調用被添加到服務定義中,文件中的代碼會不斷增加。

服務器的實現進入單獨的文件,導入生成的代碼。在這個例子中,實際的服務位於清單5的第18-25行。@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 Web服務的句柄,構建EchoRequest,將其發送到Web服務並讀取響應。

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 
相關問題