2011-10-17 20 views

Trả lời

10

tham khảo: (Nhờ Doug Hellmann) building soap service

Các Zolera Xà phòng hạ tầng giao thông (ZSI), là một phần của dự án pywebsvcs. Nó cung cấp các thư viện máy chủ và máy khách hoàn chỉnh để làm việc với SOAP. Để sử dụng nó, một nhà phát triển viết tệp WSDL (bằng tay hoặc bằng trình soạn thảo WSDL), và sau đó tạo nguồn Python cho máy khách và sơ khai cho máy chủ. Các cấu trúc dữ liệu được định nghĩa trong tệp WSDL được chuyển đổi thành các lớp Python có thể được sử dụng trong cả mã máy khách lẫn mã máy chủ.

chúng tôi đã triển khai một dịch vụ echo đơn giản trả về dưới dạng đầu ra cho dù đó là đầu ra của khách hàng. Liệt kê 1 chứa các đầu vào WSDL được tạo thủ công cho phiên bản ZSI của dịch vụ này.

Liệt kê 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> 

Để tạo mã client và server từ WSDL, thức ăn nó vào chương trình wsdl2py (có trong ZSI). Để thêm hỗ trợ cho các loại phức tạp, hãy thêm tùy chọn -b nhưng không bắt buộc đối với ví dụ đơn giản này. wsdl2py sẽ, để đáp ứng, tạo ra ba file:

Liệt kê 2

EchoServer_client.py là mã cần thiết để xây dựng một khách hàng cho các dịch vụ web 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 

Liệt kê 3

EchoServer_server.py chứa mã cần thiết để xây dựng các máy chủ dịch vụ web 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' 

Liệt kê 4

EchoServer_types.py có kiểu định nghĩa được sử dụng bởi cả khách hàng và mã máy chủ.

################################################## 
# 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) 

Khi được tạo, các tệp này không được chỉnh sửa, vì chúng sẽ được tạo lại như một phần của quá trình xây dựng bất cứ khi nào đầu vào WSDL thay đổi. Mã trong các tệp phát triển khi có nhiều loại và cuộc gọi được thêm vào định nghĩa dịch vụ.

Việc triển khai máy chủ sẽ nằm trong một tệp riêng biệt nhập mã được tạo. Trong ví dụ này, dịch vụ thực tế nằm trên các dòng 18-25 của Liệt kê 5. Trình trang trí @soapmethod định nghĩa đầu vào (một EchoRequest) và đầu ra (một EchoResponse) cho cuộc gọi. Trong ví dụ, việc thực hiện soap_Echo() chỉ điền vào giá trị đáp ứng với giá trị yêu cầu và trả về cả yêu cầu và đáp ứng. Từ đó, ZSI chăm sóc xây dựng phản hồi SOAP và gửi nó trở lại máy khách.

Bảng liệt kê 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() 

Liệt kê 6 bao gồm một mẫu về cách sử dụng các thư viện client ZSI để truy cập máy chủ từ cuối khách hàng. Tất cả những gì cần phải làm là tạo ra một xử lý cho dịch vụ web EchoServer, xây dựng một EchoRequest, gửi nó đến dịch vụ web và đọc phản hồi.

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