无法使用SOAPpy调用webservice方法
我正在尝试使用SOAPpy来调用一个网络服务:
from SOAPpy import SOAPProxy
url = 'http://www.webservicex.net/WeatherForecast.asmx'
server = SOAPProxy(url);
print server.GetWeatherByPlaceName('Dallas');
print server.GetWeatherByZipCode ('33126');
但是服务器调用失败了:
Traceback (most recent call last):
File "soap_test.py", line 6, in <module>
print server.GetWeatherByPlaceName('Dallas');
File "C:\usr\bin\Python26\lib\site-packages\SOAPpy\Client.py", line 451, in __call__
return self.__r_call(*args, **kw)
File "C:\usr\bin\Python26\lib\site-packages\SOAPpy\Client.py", line 473, in __r_call
self.__hd, self.__ma)
File "C:\usr\bin\Python26\lib\site-packages\SOAPpy\Client.py", line 387, in __call
raise p
SOAPpy.Types.faultType: <Fault soap:Client: System.Web.Services.Protocols.SoapException: Server did not recognize the value of HTTP Header SOAPAction: GetWeatherByPlaceName.
at System.Web.Services.Protocols.Soap11ServerProtocolHelper.RouteRequest()
at System.Web.Services.Protocols.SoapServerProtocol.RouteRequest(SoapServerMessage message)
at System.Web.Services.Protocols.SoapServerProtocol.Initialize()
at System.Web.Services.Protocols.ServerProtocol.SetContext(Type type, HttpContext context, HttpRequest request, HttpResponse response)
at System.Web.Services.Protocols.ServerProtocolFactory.Create(Type type, HttpContext context, HttpRequest request, HttpResponse response, Boolean& abortProcessing): >
我哪里做错了呢?
2 个回答
7
在使用 .NET 的网络服务时,你可以在调用时添加一个 soap 动作的覆盖。这就像下面这样。这段代码已经确认可以正常工作。
import SOAPpy
ns = 'http://www.webservicex.net'
url = '%s/WeatherForecast.asmx' % ns
server = SOAPpy.SOAPProxy( url, namespace=ns )
#following is required for .NET
server.config.buildWithNamespacePrefix = 0
#adding the soapaction is required for .NET
print server._sa( '%s/GetWeatherByPlaceName' %ns ).GetWeatherByPlaceName( PlaceName='Dallas' )
print server._sa( '%s/GetWeatherByZipCode' %ns ).GetWeatherByZipCode( ZipCode='33126' )
有人写了一个 类 来做类似的事情。
这是上面那个包装器的修改版,专门为 .NET 设计:
import SOAPpy
class SOAPProxy( SOAPpy.SOAPProxy ):
"""Wrapper class for SOAPpy.SOAPProxy
Designed so it will prepend the namespace to the action in the
SOAPAction HTTP headers.
"""
def __call( self, name, args, kw, ns=None, sa=None, hd=None, ma=None ):
sa = sa or self.soapaction
ns = ns or self.namespace
self.config.buildWithNamespacePrefix = 0
# Only prepend namespace if no soapaction was given.
if ns and not sa:
if ns.endswith( '/' ):
sa = '%s%s' % ( ns , name )
else:
sa = '%s/%s' % ( ns , name )
#fixup boolean args - .net wants lowercase
for arg in kw:
if isinstance( kw[ arg ], types.BooleanType ):
kw[ arg ] = SOAPpy.Types.booleanType( kw[ arg ] )
return SOAPpy.SOAPProxy.__call( self, name, args, kw, ns, sa, hd, ma )
if __name__ == '__main__':
print __doc__
4
根据错误信息,SOAPpy没有添加SOAPAction这个HTTP头。这就是为什么SOAPpy在很多服务上无法正常工作的原因。你可以试试suds,下面是一个可以正常工作的例子:
from suds.client import Client
url = 'http://www.webservicex.net/WeatherForecast.asmx?WSDL'
client = Client(url)
print client.service.GetWeatherByPlaceName('Dallas')
print client.service.GetWeatherByZipCode ('33126')