12.6. 以 WSDL 进行 SOAP 内省
优质
小牛编辑
122浏览
2023-12-01
12.6. 以 WSDL 进行 SOAP 内省
就像网络服务舞台上的所有事物, WSDL 也经历了一个充满明争暗斗而且漫长多变的历史。 我不打算讲述这段令我伤心的历史。 还有一些其他的标准提供相同的支持,但 WSDL 还是胜出,所以我们还是来学习一下如何使用它。
WSDL 最基本的功能便是让你揭示 SOAP 服务器所提供的有效方法。
例 12.8. 揭示有效方法
>>> from SOAPpy import WSDL >>> wsdlFile = 'http://www.xmethods.net/sd/2001/TemperatureService.wsdl') >>> server = WSDL.Proxy(wsdlFile) >>> server.methods.keys() [u'getTemp']
SOAPpy 包含一个 WSDL 解析器。 在本书写作之时,它被标示为开发的初级阶段,但我从来没有在解析任何 WSDL 文件时遇到问题。 | |
使用一个 WSDL 文件,你还是要用到一个 proxy 类:WSDL.Proxy,它只需一个参数: WSDL 文件。 我所说的是把存储在远程服务器上的 WSDL 的 URL, 但是这个 proxy 类对于本地的 WSDL 副本工作同样出色。创建 WSDL proxy 将会下载 WSDL 文件并解析它, 所以如果 WSDL 文件有任何问题(或者由于网络问题不能获得)你会立刻知道。 | |
WSDL proxy 类以 Python 字典 server.methods 的方式揭示有效函数。所以列表有效方法就像调用字典方法 keys() 一样简单。 |
好的,你知道这个 SOAP 服务器提供一个方法: getTemp。但是如何去调用它呢? WSDL 也在这方面提供信息。
例 12.9. 揭示一个方法的参数
>>> callInfo = server.methods['getTemp'] >>> callInfo.inparams [<SOAPpy.wstools.WSDLTools.ParameterInfo instance at 0x00CF3AD0>] >>> callInfo.inparams[0].name u'zipcode' >>> callInfo.inparams[0].type (u'http://www.w3.org/2001/XMLSchema', u'string')
server.methods 字典中记录一个 SOAPpy 的特别结构,被称为 CallInfo。 CallInfo 对象中包含着特定函数和函数参数的信息。 | |
函数参数信息存储在 callInfo.inparams 中,这是一个记录每一个参数信息的 ParameterInfo 对象的 Python 列表。 | |
每个 ParameterInfo 对象包含一个 name 属性,这便是参数名。再通过 SOAP 调用函数时,你不需要知道参数名,但 SOAP 却支持在调用函数时使用参数名的情形(类似于 Python )。如果使用参数名, WSDL.Proxy 将会正确地把这些参数关联到远程函数。 | |
每个参数都是都是显性类型的,在 XML Schema 中以数据类型定义。你可以在上一节中发现这一点:XML Schema 命名空间是我让你忽略的模版的一部分。就目前而言,你还是可以继续忽略它。 zipcode 参数是一个字符串,如果你向 WSDL.Proxy 对象传递一个 Python 字符串,它会被正确地关联和传递到服务器。 |
WSDL 还允许你自省函数的返回值。
例 12.10. 揭示方法返回值
>>> callInfo.outparams [<SOAPpy.wstools.WSDLTools.ParameterInfo instance at 0x00CF3AF8>] >>> callInfo.outparams[0].name u'return' >>> callInfo.outparams[0].type (u'http://www.w3.org/2001/XMLSchema', u'float')
与揭示函数参数的 callInfo.inparams 对应的是揭示返回值的 callInfo.outparams。它也同样是一个列表,因为通过 SOAP 调用函数时可以返回多个值,就像 Python 函数一样。 | |
ParameterInfo 对象包含 name 和 type。这个函数返回一个浮点值,它的名字是 return。 |
让我们整合一下,通过 WSDL proxy 调用一个 SOAP 网络服务。
例 12.11. 通过 WSDL proxy 调用一个 SOAP 网络服务
>>> from SOAPpy import WSDL >>> wsdlFile = 'http://www.xmethods.net/sd/2001/TemperatureService.wsdl') >>> server = WSDL.Proxy(wsdlFile) >>> server.getTemp('90210') 66.0 >>> server.soapproxy.config.dumpSOAPOut = 1 >>> server.soapproxy.config.dumpSOAPIn = 1 >>> temperature = server.getTemp('90210') *** Outgoing SOAP ****************************************************** <?xml version="1.0" encoding="UTF-8"?> <SOAP-ENV:Envelope SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/1999/XMLSchema"> <SOAP-ENV:Body> <ns1:getTemp xmlns:ns1="urn:xmethods-Temperature" SOAP-ENC:root="1"> <v1 xsi:type="xsd:string">90210</v1> </ns1:getTemp> </SOAP-ENV:Body> </SOAP-ENV:Envelope> ************************************************************************ *** Incoming SOAP ****************************************************** <?xml version='1.0' encoding='UTF-8'?> <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <SOAP-ENV:Body> <ns1:getTempResponse xmlns:ns1="urn:xmethods-Temperature" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"> <return xsi:type="xsd:float">66.0</return> </ns1:getTempResponse> </SOAP-ENV:Body> </SOAP-ENV:Envelope> ************************************************************************ >>> temperature 66.0
比直接调用 SOAP 服务时的设置简单,因为在 WSDL 文件中包含着调用服务所需要的服务 URL 和命名空间。创建 WSDL.Proxy 对象来下载 WSDL 文件,解析之,并设置一个用以调用实际的 SOAP 网络服务的 SOAPProxy 对象。 | |
WSDL.Proxy 对象一旦被创建,你可以像调用 SOAPProxy 对象一样简单地调用一个函数。这并不奇怪,WSDL.Proxy 就是一个具有自省方法的 SOAPProxy 封装套件,所以调用函数的语法也是一样的。 | |
你可以通过 server.soapproxy 访问 WSDL.Proxy 的 SOAPProxy。这对于打开查错模式很重要,这样一来当你通过 WSDL proxy 调用函数时,它的 SOAPProxy 将会把线路上来往的 XML 文档甩下来。 |