时间:2021-05-23
Kafka 样式的 soap 端点
Christopher Dix 所开发的“Kafka — XSL SOAP 工具箱”(请参阅 参考资料)是一种用于构造 SOAP 端点的 XSLT 框架。它只涵盖了 SOAP 1.1,但 Kafka 端点演示了传递 UserLand SOAP 验证器(UserLand SOAP Validator)的能力,并且根据 SOAP 1.2 对它进行更新似乎并不太困难。 清单 1展示了一个样本 Kafka 端点:求两数之和的 SOAP 服务器(一个典型而简单的 SOAP 样本)。
清单 1. 求两数之和的 Kafka SOAP 端点
<?xml version="1.0" encoding="UTF-8"?><xsl:stylesheet version="1.0" xmlns:method="http:///" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> </output> </operation> </binding> <service name="adder-service"> <port name="adder-port" binding="tns:adder-soap-binding"> <soap:address location="http://127.0.0.1:8888/add" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"/> </port> </service></definitions>清单 5提供了一个为端点用户呈现有用信息的 XSLT 脚本。它是从先前的 developerWorks 文章“WSDL processing with XSLT”(请参阅 参考资料)中所开发的一个转换改编而来的。它使用了许多自由方式(liberty)和快捷方式(尤其是在它处理 WSDL 上下文中的限定名时),但它也许可用于目前使用的大多数 WSDL 1.1 文件。
清单 5. XSLT 脚本
<?xml version="1.0" encoding="utf-8"?><xsl:stylesheet version='1.0' xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"> <xsl:output method='html'/> <!-- Lookup tables for messages, portTypes, bindings and services --> <xsl:key name='message' match="wsdl:definitions/wsdl:message" use='@name'/> <xsl:key name='port-type' match="wsdl:definitions/wsdl:portType" use='@name'/> <xsl:key name='binding' match="wsdl:definitions/wsdl:binding" use='@name'/> <xsl:key name='service' match="wsdl:definitions/wsdl:service" use='@name'/> <xsl:template match='/'> <html> <head> <title>Service summary: <xsl:value-of select='wsdl:definitions/@name'/> </title> <meta http-equiv="content-type" content="text/html" charset="UTF-8"/> </head> <body> <h1>Service summary: <xsl:value-of select='wsdl:definitions/@name'/> </h1> <p><xsl:value-of select='wsdl:definitions/@documentation'/></p> <xsl:apply-templates select="wsdl:definitions/wsdl:service"/> </body> </html> </xsl:template> <xsl:template match='wsdl:service'> <div style="background: #ccffff"> Service "<xsl:value-of select='@name'/>" hosted at <code> <xsl:value-of select='wsdl:port/soap:address/@location'/> </code> <xsl:variable name="binding" select="key('binding', substring-after(wsdl:port/@binding, ':'))" /> <xsl:variable name="port-type" select="key('port-type', substring-after($binding/@type, ':'))" /> <xsl:apply-templates select="$port-type/wsdl:operation"/> </div> </xsl:template> <xsl:template match='wsdl:operation'> <p>Operation "<b><xsl:value-of select='@name'/></b>" message details:</p> <!-- Yes, should sue CSS, but keep this example simple --> <table border="1" width="50%"> <tbody> <xsl:if test="wsdl:input"> <xsl:call-template name='message-role'> <xsl:with-param name="role-node" select="wsdl:input"/> </xsl:call-template> </xsl:if> <xsl:if test="wsdl:output"> <xsl:call-template name='message-role'> <xsl:with-param name="role-node" select="wsdl:output"/> </xsl:call-template> </xsl:if> <xsl:if test="wsdl:fault"> <xsl:call-template name='message-role'> <xsl:with-param name="role-node" select="wsdl:fault"/> </xsl:call-template> </xsl:if> </tbody> </table> </xsl:template> <xsl:template name='message-role'> <xsl:param name="role-node"/> <xsl:variable name="role-name" select="local-name($role-node)"/> <xsl:variable name="message" select="key('message', substring-after($role-node/@message, ':'))" /> <tr> <td><xsl:value-of select='$role-name'/></td> <td> <table width="100%"> <xsl:apply-templates select="$message/wsdl:part"/> </table> </td> </tr> </xsl:template> <xsl:template match='wsdl:part'> <tr> <td width="50%"><b><xsl:value-of select='@name'/></b></td> <td><xsl:value-of select='@type'/></td> </tr> </xsl:template></xsl:stylesheet>通常在 Web 服务本身所在的主机上提供该服务人性化的 WSDL 描述是很方便的。 清单 6是 清单 2的变体,它也完成这一任务。它实际上提供三种功能:
清单 6. 清单 2 的变体
#HTTP Listener code for SOAP serverimport BaseHTTPServer#The processor class is the core of the XSLT APIfrom Ft.Xml.Xslt import Processor#4XSLT uses an InputSource system for reading XMLfrom Ft.Xml import InputSourceSOAP_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 responseclass 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 classesdef _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() returnimport timefrom threading import Threadsoap_thread = Thread(None, soap_listener_function)html_thread = Thread(None, html_listener_function)soap_thread.start()#Pause before spawning the next threadtime.sleep(1)html_thread.start()通过在服务器上定义 do_GET 和 do_POST ,您可以在单个服务器实例上处理 GET 和 POST 请求,但是因为所使用的简单事件循环的性质,您可以使用线程技术在不同端口上进行侦听。这让您同时运行两个服务器实例。线程技术是方法之一,而使用异步事件处理程序是另一种方法。Python 2.2 为更轻松地支持后一种技术而引入了 asyncore 模块,我们在本专栏的上一篇文章中介绍了这种方法(请参阅 参考资料)。这一次我们将举例说明线程技术的用法。关于使用线程技术还是使用异步技术的问题,Python 2.2 文档提出了很好的建议。
仅当您的程序很大程度上受 I/O 限制时,[异步方法才是] 真正实用的。如果您的程序受处理器限制,那么抢先式调度的线程可能是您所真正需要的。但是,网络服务器很少受处理器限制。
图 1显示了易于理解的 Web 服务描述的浏览器视图。
结束语
请将这一切都看作实验素材。Kafka 已经相当落伍了 — 它似乎从 2001 年以来就没有得到过维护,并且它使用了相当差劲的 XSLT 样式(其作者坦率地承认自己是个 XSLT 菜鸟)。但其思想是非常有用的,并且很有价值。只需要作很小的努力就可以将它更新到 SOAP 1.2 并扩展其能力。我们所提供的 WSDL 表示转换也只是一个起点。也可以将它更新到 WSDL 1.2 并可扩展它以显示关于 Web 服务的更多信息。还应该更新它以利用名称空间轴和其它 XSLT 功能以便进行更为正确的处理。
XSLT 是一个沙箱,使用各种语言和环境的开发人员都可以在其中施展身手。Kafka 是由一位坚定的 .NET 开发人员开发的,但我们也可以很快地学会它和利用它。这就是拥有一种既可以处理 XML 也可处理 Web 服务的通用语言(lingua franca)的威力。我们预计可以使用用于 Web 服务的 XSLT 模块的领域将继续扩展。如果是这样,本文所提供的基本技术可能会促使 Python 程序员们马上使用这些有用的技术。
声明:本页内容来源网络,仅供用户参考;我单位不保证亦不表示资料全面及准确无误,也不保证亦不表示这些资料为最新信息,如因任何原因,本网内容或者用户因倚赖本网内容造成任何损失或损害,我单位将不会负任何法律责任。如涉及版权问题,请提交至online#300.cn邮箱联系删除。
每个网站开发者都必须了解以下Web构件:HTML4.01CSS的使用(样式表)XHTMLXML和XSLT客户端脚本服务器端脚本通过SQL管理数据Web的未来.每
一、python实现web服务器web开发首先要有web服务器才行。比如apache,但是在开发阶段最好有一个简单方便的开发服务器,容易重启进行调试,等开发调试
一.代码使用Python+Splinter开发,Splinter是一个使用Python开发的开源Web应用测试工具,它可以帮你实现自动浏览站点和与其进行交互。二
1、对web标准的理解 所谓的web标准,在一些教程文章上已经得到结论:结构化标准(XHTML、XML)、表现标准(CSS、XSLT?)、行为标准(DOM
由于接触到PythonWeb开发,正好把最简单的CGI方式研究了一下,话说在Windows下配置Python的Web开发还真的蛮麻烦的,Linux下配置倒挺容易