Проблема с проверкой SOAP-запроса в Zeep (python)

У меня проблемы с получением SOAP-запроса через Zeep, я получаю (клиентскую) ошибку проверки... Я также тестировал SoapUI, и это НЕ дает мне ту же ошибку проверки...

Приведенная ниже спецификация получена от сервера... В соответствии с этой спецификацией для выполнения запроса необходимы OrderStatus и SynchStatus.

<soapenv:Envelope xmlns:soapenv=http://schemas.xmlsoap.org/soap/envelope/ xmlns:web="WebServiceProvider">
   <soapenv:Header/>
   <soapenv:Body>
      <web:Order_Get>
         <!--Optional:-->
         <web:orderOptions>
            <web:FromDate>?</web:FromDate>
            <web:ToDate>?</web:ToDate>
            <web:OrderStatus>?</web:OrderStatus>
            <web:SynchStatus>?</web:SynchStatus>
            <!--Optional:-->
            <web:OrderNumber>?</web:OrderNumber>
            <web:FromOrderNumberToLastRecieved>?</web:FromOrderNumberToLastRecieved>
            <web:PaymentStatus>?</web:PaymentStatus>
         </web:orderOptions>
      </web:Order_Get>
   </soapenv:Body>
</soapenv:Envelope>

Однако выполнение этого из SoapUI без OrderStatus и SynchStatus даст мне список всех заказов на указанные даты:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:web="WebServiceProvider">
   <soapenv:Header/>
   <soapenv:Body>
      <web:Order_Get>
         <web:orderOptions>
            <web:FromDate>2021-03-30</web:FromDate>
            <web:ToDate>2021-03-31</web:ToDate>
         </web:orderOptions>
      </web:Order_Get>
   </soapenv:Body>
</soapenv:Envelope>

Я хочу сделать то же самое с Zeep (https://github.com/mvantellingen/python-zeep), но проверка клиента не удалась...

Я инициирую запрос со следующим кодом:

api_url = 'https://abc.se/Webservice20/v3.0/webservice.asmx?WSDL'
session.auth = HTTPDigestAuth(username, password)
api = Client(api_url, transport=Transport(session=session))

И затем я пытаюсь выполнить следующий запрос:

order_options = {
  'FromDate': '2021-03-30',
  'ToDate': '2021-03-31',
}
orders = api.service.Order_Get(orderOptions=order_options)

Это приведет к следующей ошибке:

zeep.exceptions.ValidationError: Missing element OrderStatus (Order_Get.orderOptions.OrderStatus)

Если я добавлю OrderStatus в запрос, я получу ошибку проверки, говорящую об отсутствии SynchStatus. Когда это также было добавлено, запрос отправляется на сервер.

т.е. похоже, что клиент zeep более строг в отношении проверки данных в запросе, чем сервер... Есть ли способ заставить клиента пропустить эту проверку?

Спасибо заранее!


person Tobias Gårdner    schedule 01.04.2021    source источник


Ответы (2)


похоже, что клиент zeep более строг в отношении проверки данных в запросе, чем сервер...

Похоже на то.

Глядя на запрос, который генерирует SoapUI на основе WSDL, два поля, которые вы упомянули, являются обязательными:

 <web:orderOptions>
    <web:FromDate>?</web:FromDate>
    <web:ToDate>?</web:ToDate>
    <web:OrderStatus>?</web:OrderStatus>
    <web:SynchStatus>?</web:SynchStatus>
    <!--Optional:-->
    <web:OrderNumber>?</web:OrderNumber>
    <web:FromOrderNumberToLastRecieved>?</web:FromOrderNumberToLastRecieved>
    <web:PaymentStatus>?</web:PaymentStatus>
 </web:orderOptions>

Так что ошибка, которую отображает клиент zeep, верна. Zeep проверяет WSDL и генерирует соответствующий код для использования типов в контракте. В вашем контракте WSDL указано, что OrderStatus и SynchStatus являются обязательными. Тот факт, что сервер не проверяет их, указывает на проблему: веб-служба не соблюдает свой собственный задокументированный контракт.

WSDL и поведение веб-службы должны быть одинаковыми. Я предлагаю вам связаться с владельцами веб-сервисов и спросить об этом поведении. Это может быть проверка, отсутствующая на сервере, и то, что вы получаете, является просто побочным эффектом этого, или поведение преднамеренное, но кто-то забыл обновить WSDL, чтобы сказать, что вы также можете сделать вызов без этих параметров.

Между тем обходной путь очень прост. Загрузите WSDL, измените его, чтобы сделать два поля необязательными, затем передайте этот измененный WSDL, чтобы zeep сгенерировал код вместо использования исходного WSDL. Однако вам следует уточнить это у поставщика веб-услуг. Если это действительно пренебрежение кем-то, это может быть замечено в какой-то момент и исправлено, в результате чего ваш обходной вызов не пройдет проверку сервера из-за отсутствующих полей.

person Bogdan    schedule 01.04.2021

Поискал немного больше и нашел обходной путь в этом сообщении: Получение zeep.exceptions.ValidationError: Отсутствует элемент для метода, который работал с suds

Итак, решение в моем случае выглядит так:

from zeep import xsd
...

order_options = {
  'FromDate': '2021-03-30',
  'ToDate': '2021-03-31',
  'OrderStatus': xsd.SkipValue,
  'SynchStatus': xsd.SkipValue,
}

response = api.service.Order_Get(orderOptions=order_options)

Это заблокирует zeep от проверки параметров OrderStatus и SynchStatus на стороне клиента.

person Tobias Gårdner    schedule 01.04.2021
comment
Zeep автоматически проверит, установлены ли все необходимые значения при вызове операции. Если вы хотите, чтобы значение игнорировалось и исключалось из сгенерированного XML, вы можете назначить константу zeep.xsd.SkipValue (*). Хорошая находка. +1 - person Bogdan; 01.04.2021