Изменение URL сервиса при доступе к SOAP через прокси с помощью Zeep

В моем приложении мне нужно получить доступ к внутреннему (корпоративному) Soap API. Для этого доступа я использовал Zeep до сих пор. Но теперь доступ должен проходить через прокси, и фактический адрес API должен быть преобразован в виртуальный адрес прокси.

Создание клиента Zeep также работает правильно, и я могу получить доступ к файлам WSDL. Однако проблема возникает при вызове соответствующей службы, потому что Zeep берет соответствующий URL-адрес из файла WSDL, и он не соответствует виртуальному адресу прокси.

Я попытаюсь проиллюстрировать проблему ниже с помощью моего конкретного кода:

Предположим, что адрес SOAP API — https://original-soap/wsdl?service=<service_name>.

В прокси есть отображение из https://origial-soap в http://virtual-soap.

Таким образом, Zeep должен использовать адрес http://virtual-soap/wsdl?service=<service_name>.

Я инициализирую свой клиент Zeep следующим образом:

from requests.auth import HTTPBasicAuth
from requests import Session
from zeep import Client
from zeep.transports import Transport
from zeep.helpers import serialize_object

session = Session()
session.proxies = {
    'http': 'http://<proxy_host>:<proxy_port>',
    'https': 'http://<proxy_host>:<proxy_port>',
}
proxy_header = {
    "Proxy-Authorization": "Bearer <proxy_access_token>"
}
session.headers.update(proxy_header)
session.verify = False
session.auth = HTTPBasicAuth(<soap_user>, <soap_password>)
transport = Transport(session=session)

client = Client(wsdl='http://virtual-saop/wsdl?service=<service_name>', transport=transport)

print('CLIENT INITIALIZED') # <-- This print command is executed

soap_result = client.service['<service_function_name>'](<function parameters>) # <-- Connectivity errors occur here

Итак, мой вопрос заключается в том, как я могу также изменить URL-адрес, который Zeep использует при вызове службы, чтобы здесь также использовался виртуальный адрес.

Спасибо за любую помощь заранее!

Благодаря @Bogdan я решил проблему, используя следующий код для инициализации службы:

service = client.create_service(
    client.service._binding.name, client.service._binding_options['address'].replace('https://original-soap:443', 'http://virtual-soap:80', 1)
)
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
2
0
116
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Есть еще один способ создать ServiceProxy, который должен это делать.

См. документацию по адресу https://docs.python-zeep.org/en/master/client.html#creating-new-serviceproxy-objects

Экземпляр ServiceProxy по умолчанию создается с использованием адреса в WSDL, но описанный выше способ создания ServiceProxy позволяет больше контролировать адрес.

Значение для {http://my-target-namespace-here}myBinding — это ваш идентификатор привязки. Если вы сделаете python -mzeep https://original-soap/wsdl, вы должны получить вывод, подобный этому (я использую здесь какой-то онлайн-пример для демонстрационных целей, поскольку у меня нет доступа к вашему WSDL):

> python -mzeep http://www.dneonline.com/calculator.asmx?WSDL

    
Prefixes:
     xsd: http://www.w3.org/2001/XMLSchema
     ns0: http://tempuri.org/

Global elements:
     ns0:Add(intA: xsd:int, intB: xsd:int)
     ns0:AddResponse(AddResult: xsd:int)
     ns0:Divide(intA: xsd:int, intB: xsd:int)
     ns0:DivideResponse(DivideResult: xsd:int)
     ns0:Multiply(intA: xsd:int, intB: xsd:int)
     ns0:MultiplyResponse(MultiplyResult: xsd:int)
     ns0:Subtract(intA: xsd:int, intB: xsd:int)
     ns0:SubtractResponse(SubtractResult: xsd:int)
     

Global types:
     xsd:anyType
     xsd:ENTITIES
     xsd:ENTITY
     xsd:ID
     xsd:IDREF
     xsd:IDREFS
     xsd:NCName
     xsd:NMTOKEN
     xsd:NMTOKENS
     xsd:NOTATION
     xsd:Name
     xsd:QName
     xsd:anySimpleType
     xsd:anyURI
     xsd:base64Binary
     xsd:boolean
     xsd:byte
     xsd:date
     xsd:dateTime
     xsd:decimal
     xsd:double
     xsd:duration
     xsd:float
     xsd:gDay
     xsd:gMonth
     xsd:gMonthDay
     xsd:gYear
     xsd:gYearMonth
     xsd:hexBinary
     xsd:int
     xsd:integer
     xsd:language
     xsd:long
     xsd:negativeInteger
     xsd:nonNegativeInteger
     xsd:nonPositiveInteger
     xsd:normalizedString
     xsd:positiveInteger
     xsd:short
     xsd:string
     xsd:time
     xsd:token
     xsd:unsignedByte
     xsd:unsignedInt
     xsd:unsignedLong
     xsd:unsignedShort

Bindings:
     Soap11Binding: {http://tempuri.org/}CalculatorSoap
     Soap12Binding: {http://tempuri.org/}CalculatorSoap12

Service: Calculator
     Port: CalculatorSoap (Soap11Binding: {http://tempuri.org/}CalculatorSoap)
         Operations:
            Add(intA: xsd:int, intB: xsd:int) -> AddResult: xsd:int
            Divide(intA: xsd:int, intB: xsd:int) -> DivideResult: xsd:int
            Multiply(intA: xsd:int, intB: xsd:int) -> MultiplyResult: xsd:int
            Subtract(intA: xsd:int, intB: xsd:int) -> SubtractResult: xsd:int

     Port: CalculatorSoap12 (Soap12Binding: {http://tempuri.org/}CalculatorSoap12)
         Operations:
            Add(intA: xsd:int, intB: xsd:int) -> AddResult: xsd:int
            Divide(intA: xsd:int, intB: xsd:int) -> DivideResult: xsd:int
            Multiply(intA: xsd:int, intB: xsd:int) -> MultiplyResult: xsd:int
            Subtract(intA: xsd:int, intB: xsd:int) -> SubtractResult: xsd:int

Если вы посмотрите на результат этого при выполнении команды на вашем WSDL, вы увидите раздел «Привязки». Вот откуда вы получаете значение, которое, скорее всего, будет для Soap11Binding (большинство сервисов предоставляют только одну привязку, этот предоставляет две, по одной для каждой версии протокола SOAP).

Для http://my-endpoint.com/acceptance/ в документации вы должны заменить свой новый адрес SOAP (то есть новое место, куда вы хотите отправить запрос на обслуживание сейчас). Судя по вашему примеру, это должно быть http://virtual-soap/something, где something — это исходный путь от исходного адреса SOAP, который находится внутри WSDL (опять же, поскольку у меня нет доступа к вашему WSDL, вы должны посмотреть, какую часть адреса вы нужно заменить, а что останется).

Что касается того, какую операцию вы хотите вызвать, это не меняется. Вы называете это так же. Те же методы существуют, потому что вы не меняете контракт на обслуживание, вы просто меняете, куда вы хотите отправить запрос.

Здравствуйте @Bodgan, большое спасибо за ваш ответ. К сожалению, я не полностью понимаю документацию. Не могли бы вы привести пример инициализации службы? Что означают '{http://my-target-namespace-here}myBinding' и 'http://my-endpoint.com/acceptance/'? И где мне указать имя операции, которую я хочу вызвать?

Brian 16.04.2023 14:49

Другие вопросы по теме