utils/soap: handle case where Fault.detail is a byte string (#75649)

This commit is contained in:
Benjamin Dauvergne 2023-03-21 12:14:54 +01:00 committed by Gitea
parent 9c85b556f2
commit 1f93f5506d
2 changed files with 35 additions and 5 deletions

View File

@ -49,13 +49,15 @@ class SOAPFault(SOAPError):
log_error = False
def __init__(self, client, fault):
dico = fault.__dict__
if isinstance(dico.get('detail'), etree._Element):
dico['detail'] = etree.tostring(dico['detail']).decode()
detail = fault.detail
if isinstance(detail, etree._Element):
fault.detail = etree.tostring(detail).decode()
elif isinstance(detail, bytes):
fault.detail = detail.decode()
super().__init__(
f'SOAP service at {client.wsdl.location} returned an error "{fault.message or fault.code}"',
data={
'soap_fault': dico,
'soap_fault': fault.__dict__,
},
)

View File

@ -18,6 +18,7 @@ from unittest import mock
import pytest
import requests
import responses
from django.utils.encoding import force_bytes
from zeep import Settings
from zeep.exceptions import Fault, TransportError, XMLParseError
@ -25,7 +26,7 @@ from zeep.plugins import Plugin
from passerelle.utils import Request
from passerelle.utils.jsonresponse import APIError
from passerelle.utils.soap import SOAPClient
from passerelle.utils.soap import SOAPClient, SOAPFault
WSDL = 'tests/data/soap.wsdl'
@ -155,3 +156,30 @@ def test_api_error(mocked_send, caplog):
operation_proxy_call.side_effect = XMLParseError('Unexpected element')
with pytest.raises(APIError, match=r'Unexpected element'):
client.service.GetLastTradePrice(tickerSymbol='banana')
@responses.activate
def test_fault_detail_on_500():
from passerelle.utils.jsonresponse import to_json
responses.add(
responses.POST,
'http://example.com/stockquote',
body=b'''<?xml version='1.0' encoding='utf-8'?>
<soap-env:Envelope xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/">
<soap-env:Body>
<ns0:TradePrice xmlns:ns0="http://example.com/stockquote.xsd">
<skipMe>1.2</skipMe>
<price>4.20</price>
</ns0:TradePrice>
</soap-env:Body>
</soap-env:Envelope>''',
status=500,
)
soap_resource = SOAPResource()
client = SOAPClient(soap_resource, api_error=True)
with pytest.raises(SOAPFault) as exc:
client.service.GetLastTradePrice(tickerSymbol='banana')
response = to_json().err_to_response(exc.value)
assert response['err'] == 1
assert 'xmlns:soap' in response['data']['soap_fault']['detail']