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