Перепишите URL с помощью клиента suds

Мы используем 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()

Если я отлажусь в этом, и думаю, что это произойдет:

  1. URL, который я предоставляю в Client(url) выбирается клиентской библиотекой suds
  2. suds разбирает результат. Это обнаружить другие места WSDL в первом WSDL
  3. suds хочет получить другие wsdl-файлы, используя URL-адреса, которые были найдены в первом wsdl.
  4. Эти URL не работают. Они содержат неправильный протокол: http вместо https.
  5. suds пытается общаться по http с сервером https
  6. сервер https останавливает связь
  7. на стороне клиента я вижу: BadStatusLine

Но как обойти это? У меня есть только доступ к клиенту. Вот почему я прошу "обходной путь", а не решение проблемы:-)

1 ответ

Решение

Я нашел очень грязное решение.

Я временно заменяю метод urllib2.OpenerDirector.open().

Таким образом, я могу исправить неработающие URL-адреса в 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
Другие вопросы по тегам