Python Web 服务开发人员: 三股力量:Python、Web 服务和 XSLT
2008-09-30 13:02:15 来源:WEB开发网通常在 Web 服务本身所在的主机上提供该服务人性化的 WSDL 描述是很方便的。 清单 6是 清单 2的变体,它也完成这一任务。它实际上提供三种功能:
对于端口 9000 上的 GET 请求:提供该 Web 服务调用消息的易于理解的描述
对于端口 8888 上的 GET 请求:提供未经处理的 WSDL 文件
对于端口 8888 上的 POST 请求:执行 SOAP 请求。
清单 6. 清单 2 的变体
#HTTP Listener code for SOAP server
import BaseHTTPServer
#The processor class is the core of the XSLT API
from Ft.Xml.Xslt import Processor
#4XSLT uses an InputSource system for reading XML
from Ft.Xml import InputSource
SOAP_IMPL_FILE = "add.xsl"
WSDL_FILE = "listing4.xml"
HTML_VIEW_TRANSFORM = "listing5.xslt"
class KafkaSoapHandler(BaseHTTPServer.BaseHTTPRequestHandler):
def init(cls):
from Ft.Lib import Uri
#Set up a processor instance to use
cls.processor = Processor.Processor()
#Load it with add.xsl
add_uri = Uri.OsPathToUri(SOAP_IMPL_FILE, attemptAbsolute=1)
transform = InputSource.DefaultFactory.fromUri(add_uri)
cls.processor.appendStylesheet(transform)
#Now the processor is prepped with a transform and can be used
#over and over for the same transform
#Prep for WSDL requests
cls.wsdl = open(WSDL_FILE).read()
return
#Make init() a static method of the class
init = classmethod(init)
def do_POST(self):
clen = self.headers.getheader('content-length')
if clen:
clen = int(clen)
else:
print 'POST ERROR: missing content-length'
return
if self.path != '/add':
self.send_error(404)
input_body = self.rfile.read(clen)
#input_body is the request SOAP envelope and contents
response_body = self._run_through_kafka(input_body)
#response_body is the response SOAP envelope and contents
_send_response(self, 200, 'OK', response_body)
return
def do_GET(self):
#response_body is the WSDL file
_send_response(self, 200, 'OK', self.wsdl)
return
def _run_through_kafka(self, body):
#In 4Suite all InputSources have base URIs in case they refer to
#other URIs in some way and resolution is required.
#The SOAP messages will not have any such URI references,
#So use a dummy base URI
source = InputSource.DefaultFactory.fromString(body, "urn:dummy")
response = self.processor.run(source)
return response
class HtmlHandler(BaseHTTPServer.BaseHTTPRequestHandler):
def init(cls):
from Ft.Lib import Uri
#Perform the transform once and store the result
processor = Processor.Processor()
html_desc_uri = Uri.OsPathToUri(HTML_VIEW_TRANSFORM,
attemptAbsolute=1)
transform = InputSource.DefaultFactory.fromUri(html_desc_uri)
processor.appendStylesheet(transform)
wsdl_uri = Uri.OsPathToUri(WSDL_FILE, attemptAbsolute=1)
source = InputSource.DefaultFactory.fromUri(wsdl_uri)
cls.html_desc = processor.run(source)
return
#Make init() a static class method
init = classmethod(init)
def do_GET(self):
#response_body is the WSDL file
_send_response(self, 200, 'OK', self.html_desc)
return
#Turn _send_response into a global function
#for sharing between the classes
def _send_response(handler, code, msg, body):
#Prepare a normal response
handler.send_response(200, 'OK')
#Send standard HTP headers
handler.send_header('Content-type', 'text/html; charset=utf-8')
handler.send_header("Connection", "close")
handler.send_header("Accept-Ranges", "bytes")
handler.send_header('Content-length', len(body)-1)
handler.end_headers()
#Send the response prepared by the SOAP end point
handler.wfile.write(body)
return
def soap_listener_function():
listen_on_port = 8888
#Set up to run on local machine
server_address = ('127.0.0.1', listen_on_port)
KafkaSoapHandler.init()
httpd = BaseHTTPServer.HTTPServer(server_address, KafkaSoapHandler)
print "Listening for GET and POST on port", listen_on_port
#Go into a the main event loop
httpd.serve_forever()
def html_listener_function():
listen_on_port = 9000
#Set up to run on local machine
server_address = ('127.0.0.1', listen_on_port)
HtmlHandler.init()
httpd = BaseHTTPServer.HTTPServer(server_address, HtmlHandler)
print "Listening for GET on port", listen_on_port
#Go into a the main event loop
httpd.serve_forever()
return
import time
from threading import Thread
soap_thread = Thread(None, soap_listener_function)
html_thread = Thread(None, html_listener_function)
soap_thread.start()
#Pause before spawning the next thread
time.sleep(1)
html_thread.start()
更多精彩
赞助商链接