用 suds 客户端重写 URL
Rewrite URL with suds Client
我们使用 suds 访问肥皂服务。
url = 'https://example.com/scr-webservices/soap/AuthenticationService?wsdl'
client = Client(url)
client.login()
结果:
File ".../suds/client.py", line 112, in __init__
self.wsdl = reader.open(url)
File ".../suds/reader.py", line 157, in open
d = self.fn(url, self.options)
File ".../suds/wsdl.py", line 159, in __init__
self.build_schema()
File ".../suds/wsdl.py", line 220, in build_schema
self.schema = container.load(self.options)
File ".../suds/xsd/schema.py", line 93, in load
child.open_imports(options)
File ".../suds/xsd/schema.py", line 305, in open_imports
imported = imp.open(options)
File ".../suds/xsd/sxbasic.py", line 542, in open
result = self.download(options)
File ".../suds/xsd/sxbasic.py", line 560, in download
d = reader.open(url)
File ".../suds/reader.py", line 84, in open
d = self.download(url)
File ".../suds/reader.py", line 100, in download
fp = self.options.transport.open(Request(url))
File ".../suds/transport/https.py", line 60, in open
return HttpTransport.open(self, request)
File ".../suds/transport/http.py", line 105, in open
fp = self.invoke(request, retfile=True)
File ".../suds/transport/http.py", line 153, in invoke
u2response = urlopener.open(u2request, timeout=tm)
File "/usr/lib/python2.7/urllib2.py", line 429, in open
response = self._open(req, data)
File "/usr/lib/python2.7/urllib2.py", line 447, in _open
'_open', req)
File "/usr/lib/python2.7/urllib2.py", line 407, in _call_chain
result = func(*args)
File "/usr/lib/python2.7/urllib2.py", line 1228, in http_open
return self.do_open(httplib.HTTPConnection, req)
File "/usr/lib/python2.7/urllib2.py", line 1201, in do_open
r = h.getresponse(buffering=True)
File "/usr/lib/python2.7/httplib.py", line 1136, in getresponse
response.begin()
File "/usr/lib/python2.7/httplib.py", line 453, in begin
version, status, reason = self._read_status()
File "/usr/lib/python2.7/httplib.py", line 417, in _read_status
raise BadStatusLine(line)
httplib.BadStatusLine: ''
client.service.login()
如果我对其进行调试,并认为会发生这种情况:
- 我在
Client(url)
中提供的 url 被 suds 客户端库获取
- suds 解析结果。它在第一个 wsdl
中发现其他 wsdl 位置
- suds 想通过访问在第一个 wsdl 中找到的 URL 来获取其他 wsdl 文件。
- 这些 URL 已损坏。它们包含错误的协议:http 而不是 https。
- suds 尝试与 https 服务器进行 http 通信
- https服务器停止通信
- 在客户端我看到:BadStatusLine
但是如何解决这个问题?我只能访问客户端。这就是为什么我要求 "work around" 而不是解决方案:-)
我找到了一个非常肮脏的解决方案。
我正在临时替换 urllib2.OpenerDirector.open() 方法。
这样我就可以修复我收到的 wsdl 中损坏的 URL。我将网址从 "http" 更改为 "https"。
我们非常欢迎更好的解决方案:-)
第一个解决方案是提供一个替代传输对象。但并非所有客户端-服务器 http 连接似乎都使用这种传输方式。
url = 'https://localhost:40443/scr-webservices/soap/AuthenticationService?wsdl'
import ssl
import mock
from suds.client import Client
from urllib2 import OpenerDirector
def rewrite_url(url):
magic = 'http:'
if magic in url:
url = url.replace(magic, 'https:')
return url
def my_open_director_open(original):
def my_open(self, request_obj, **kwargs):
request_obj.host = request_obj.get_host()
request_obj._Request__original = rewrite_url(request_obj._Request__original)
request_obj.type = 'https'
return original(self, request_obj, **kwargs)
return my_open
with mock.patch('ssl._create_default_https_context', ssl._create_unverified_context):
opener_director_open_original = OpenerDirector.open
try:
OpenerDirector.open = my_open_director_open(opener_director_open_original)
client = Client(url)
print(client)
print(client.service.remote_procedure_to_call())
finally:
OpenerDirector.open = opener_director_open_original
我们使用 suds 访问肥皂服务。
url = 'https://example.com/scr-webservices/soap/AuthenticationService?wsdl'
client = Client(url)
client.login()
结果:
File ".../suds/client.py", line 112, in __init__
self.wsdl = reader.open(url)
File ".../suds/reader.py", line 157, in open
d = self.fn(url, self.options)
File ".../suds/wsdl.py", line 159, in __init__
self.build_schema()
File ".../suds/wsdl.py", line 220, in build_schema
self.schema = container.load(self.options)
File ".../suds/xsd/schema.py", line 93, in load
child.open_imports(options)
File ".../suds/xsd/schema.py", line 305, in open_imports
imported = imp.open(options)
File ".../suds/xsd/sxbasic.py", line 542, in open
result = self.download(options)
File ".../suds/xsd/sxbasic.py", line 560, in download
d = reader.open(url)
File ".../suds/reader.py", line 84, in open
d = self.download(url)
File ".../suds/reader.py", line 100, in download
fp = self.options.transport.open(Request(url))
File ".../suds/transport/https.py", line 60, in open
return HttpTransport.open(self, request)
File ".../suds/transport/http.py", line 105, in open
fp = self.invoke(request, retfile=True)
File ".../suds/transport/http.py", line 153, in invoke
u2response = urlopener.open(u2request, timeout=tm)
File "/usr/lib/python2.7/urllib2.py", line 429, in open
response = self._open(req, data)
File "/usr/lib/python2.7/urllib2.py", line 447, in _open
'_open', req)
File "/usr/lib/python2.7/urllib2.py", line 407, in _call_chain
result = func(*args)
File "/usr/lib/python2.7/urllib2.py", line 1228, in http_open
return self.do_open(httplib.HTTPConnection, req)
File "/usr/lib/python2.7/urllib2.py", line 1201, in do_open
r = h.getresponse(buffering=True)
File "/usr/lib/python2.7/httplib.py", line 1136, in getresponse
response.begin()
File "/usr/lib/python2.7/httplib.py", line 453, in begin
version, status, reason = self._read_status()
File "/usr/lib/python2.7/httplib.py", line 417, in _read_status
raise BadStatusLine(line)
httplib.BadStatusLine: ''
client.service.login()
如果我对其进行调试,并认为会发生这种情况:
- 我在
Client(url)
中提供的 url 被 suds 客户端库获取 - suds 解析结果。它在第一个 wsdl 中发现其他 wsdl 位置
- suds 想通过访问在第一个 wsdl 中找到的 URL 来获取其他 wsdl 文件。
- 这些 URL 已损坏。它们包含错误的协议:http 而不是 https。
- suds 尝试与 https 服务器进行 http 通信
- https服务器停止通信
- 在客户端我看到:BadStatusLine
但是如何解决这个问题?我只能访问客户端。这就是为什么我要求 "work around" 而不是解决方案:-)
我找到了一个非常肮脏的解决方案。
我正在临时替换 urllib2.OpenerDirector.open() 方法。
这样我就可以修复我收到的 wsdl 中损坏的 URL。我将网址从 "http" 更改为 "https"。
我们非常欢迎更好的解决方案:-)
第一个解决方案是提供一个替代传输对象。但并非所有客户端-服务器 http 连接似乎都使用这种传输方式。
url = 'https://localhost:40443/scr-webservices/soap/AuthenticationService?wsdl'
import ssl
import mock
from suds.client import Client
from urllib2 import OpenerDirector
def rewrite_url(url):
magic = 'http:'
if magic in url:
url = url.replace(magic, 'https:')
return url
def my_open_director_open(original):
def my_open(self, request_obj, **kwargs):
request_obj.host = request_obj.get_host()
request_obj._Request__original = rewrite_url(request_obj._Request__original)
request_obj.type = 'https'
return original(self, request_obj, **kwargs)
return my_open
with mock.patch('ssl._create_default_https_context', ssl._create_unverified_context):
opener_director_open_original = OpenerDirector.open
try:
OpenerDirector.open = my_open_director_open(opener_director_open_original)
client = Client(url)
print(client)
print(client.service.remote_procedure_to_call())
finally:
OpenerDirector.open = opener_director_open_original