misc: replace interception of zeep.exceptions.Fault (#75649)
* replaced by no interception at all in some places, as SOAPError inherit from APIError * replaced by SOAPFault in cartads_cs as there was a custom handling of the soap Faults. * new SOAPValidationError error is added to handle translation to APIError with 400 status and not logging as an error of the connector.
This commit is contained in:
parent
1f93f5506d
commit
2de6325c6d
|
@ -21,10 +21,8 @@ import urllib
|
|||
import lxml.etree
|
||||
from django.db import models
|
||||
from django.utils import dateformat, dateparse
|
||||
from django.utils.encoding import force_str
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from zeep import helpers
|
||||
from zeep.exceptions import Fault
|
||||
|
||||
from passerelle.base.models import BaseResource
|
||||
from passerelle.utils.api import endpoint
|
||||
|
@ -58,10 +56,7 @@ class ATALConnector(BaseResource):
|
|||
|
||||
def _soap_call(self, wsdl, method, **kwargs):
|
||||
client = self._soap_client(wsdl=wsdl)
|
||||
try:
|
||||
return getattr(client.service, method)(**kwargs)
|
||||
except Fault as e:
|
||||
raise APIError(force_str(e))
|
||||
return getattr(client.service, method)(**kwargs)
|
||||
|
||||
def _basic_ref(self, wsdl, method):
|
||||
soap_res = self._soap_call(wsdl=wsdl, method=method)
|
||||
|
|
|
@ -27,7 +27,6 @@ from xml.etree import ElementTree as etree
|
|||
|
||||
import pdfrw
|
||||
import pdfrw.findobjs
|
||||
import zeep.exceptions
|
||||
import zeep.helpers as zeep_helpers
|
||||
from Cryptodome.Cipher import AES
|
||||
from django.conf import settings
|
||||
|
@ -45,6 +44,7 @@ from passerelle.base.models import BaseResource
|
|||
from passerelle.base.signature import sign_url
|
||||
from passerelle.utils.api import endpoint
|
||||
from passerelle.utils.jsonresponse import APIError, JSONEncoder
|
||||
from passerelle.utils.soap import SOAPFault
|
||||
|
||||
|
||||
def cartads_file_location(instance, filename):
|
||||
|
@ -326,7 +326,7 @@ class AbstractCartaDSCS(BaseResource):
|
|||
for dossier in CartaDSDossier.objects.filter(cartads_id_dossier__isnull=False, deleted=False):
|
||||
try:
|
||||
dossier.cartads_steps_cache = {'steps': self.get_dossier_steps(client, token, dossier)}
|
||||
except zeep.exceptions.Fault as e:
|
||||
except SOAPFault as e:
|
||||
if "n'existe pas" in str(e):
|
||||
dossier.deleted = True
|
||||
dossier.save()
|
||||
|
@ -336,7 +336,7 @@ class AbstractCartaDSCS(BaseResource):
|
|||
dossier.cartads_cache_code_acces = client_suivi.service.GetMotPasse(
|
||||
self.get_token(), dossier.cartads_id_dossier
|
||||
)
|
||||
except zeep.exceptions.Fault as e:
|
||||
except SOAPFault as e:
|
||||
self.logger.exception('error getting access code (%s) (%s)', dossier.id, e)
|
||||
try:
|
||||
infos_dossier = client_dossier.service.GetInfosDossier(
|
||||
|
@ -347,7 +347,7 @@ class AbstractCartaDSCS(BaseResource):
|
|||
dossier.cartads_cache_infos = json.loads(
|
||||
json.dumps(zeep_helpers.serialize_object(infos_dossier), cls=JSONEncoder)
|
||||
)
|
||||
except zeep.exceptions.Fault as e:
|
||||
except SOAPFault as e:
|
||||
self.logger.exception('error getting dossier infos (%s) (%s)', dossier.id, e)
|
||||
dossier.save()
|
||||
self.sync_subscribers_role(dossier)
|
||||
|
@ -951,7 +951,7 @@ class AbstractCartaDSCS(BaseResource):
|
|||
),
|
||||
},
|
||||
)
|
||||
except zeep.exceptions.Fault as e:
|
||||
except SOAPFault as e:
|
||||
self.logger.exception('error pushing file item %d (%s)', piece.id, e)
|
||||
continue
|
||||
else:
|
||||
|
@ -994,7 +994,7 @@ class AbstractCartaDSCS(BaseResource):
|
|||
),
|
||||
},
|
||||
)
|
||||
except zeep.exceptions.Fault as e:
|
||||
except SOAPFault as e:
|
||||
self.logger.exception('error pushing file item %d (%s)', piece.id, e)
|
||||
else:
|
||||
assert resp is None
|
||||
|
@ -1047,7 +1047,7 @@ class AbstractCartaDSCS(BaseResource):
|
|||
'InformationsComplementaires': key_value_of_stringstring(infos),
|
||||
},
|
||||
)
|
||||
except zeep.exceptions.Fault as e:
|
||||
except SOAPFault as e:
|
||||
self.logger.exception('error pushing daact file item %d (%s)', piece.id, e)
|
||||
else:
|
||||
assert resp is None
|
||||
|
@ -1177,7 +1177,7 @@ class AbstractCartaDSCS(BaseResource):
|
|||
resp = client.service.ActiverServiceSuiviNumerique(
|
||||
self.get_token(), dossier_number, dossier_password
|
||||
)
|
||||
except zeep.exceptions.Fault as e:
|
||||
except SOAPFault as e:
|
||||
self.logger.error('error joining dossier %s (%s)', dossier_number, e)
|
||||
raise APIError('error joining dossier (wrong password?)')
|
||||
id_dossier = int(resp)
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
import collections
|
||||
|
||||
import zeep
|
||||
import zeep.exceptions
|
||||
import zeep.helpers
|
||||
import zeep.xsd
|
||||
from django.db import models
|
||||
|
@ -127,16 +126,7 @@ class SOAPConnector(BaseResource, HTTPResource):
|
|||
payload[k] = value[0]
|
||||
payload.update(post_data or {})
|
||||
payload = unflatten(payload)
|
||||
try:
|
||||
soap_response = getattr(self.client.service, method_name)(**payload)
|
||||
except zeep.exceptions.Fault as e:
|
||||
fault_details = {}
|
||||
for attrib in ['actor', 'code', 'message', 'subcode']:
|
||||
fault_details[attrib] = getattr(e, attrib, None)
|
||||
raise APIError('soap:Fault', data=fault_details)
|
||||
except zeep.exceptions.ValidationError as e:
|
||||
e.status_code = 400
|
||||
raise e
|
||||
soap_response = getattr(self.client.service, method_name)(**payload)
|
||||
serialized = zeep.helpers.serialize_object(soap_response)
|
||||
json_response = jsonify(serialized)
|
||||
return {'err': 0, 'data': json_response}
|
||||
|
|
|
@ -24,7 +24,6 @@ from django.core.cache import cache
|
|||
from django.db import models
|
||||
from django.utils import timezone
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from zeep.exceptions import Fault as WebFault
|
||||
from zeep.helpers import serialize_object
|
||||
|
||||
from passerelle.base.models import BaseResource
|
||||
|
@ -227,12 +226,7 @@ class DPark(BaseResource):
|
|||
def call(self, operation, *args, **kwargs):
|
||||
service = get_service(self)
|
||||
bypass_erroneous_reply = kwargs.pop('bypass_erroneous_reply', False)
|
||||
try:
|
||||
reply = getattr(service, operation)(*args, **kwargs)
|
||||
except (WebFault,) as exc:
|
||||
raise APIError('ServiceError: %s' % exc)
|
||||
except (Exception,) as exc:
|
||||
raise APIError('Error: %s' % exc)
|
||||
reply = getattr(service, operation)(*args, **kwargs)
|
||||
reply_code = getattr(reply, 'CodeRetour', None) or getattr(reply, 'Code_Retour', None)
|
||||
reply_message = getattr(reply, 'MessageRetour', None) or getattr(reply, 'Lib_Retour', None)
|
||||
if reply_code != '01' and not bypass_erroneous_reply:
|
||||
|
|
|
@ -76,10 +76,7 @@ class ToulouseMaelis(BaseResource, HTTPResource):
|
|||
def call(self, wsdl_short_name, service, **kwargs):
|
||||
client = self.get_client(wsdl_short_name)
|
||||
method = getattr(client.service, service)
|
||||
try:
|
||||
response = method(**kwargs)
|
||||
except zeep.exceptions.Fault as e:
|
||||
raise APIError(e.message)
|
||||
response = method(**kwargs)
|
||||
return serialize_object(response)
|
||||
|
||||
def check_status(self):
|
||||
|
|
|
@ -21,7 +21,7 @@ from requests import RequestException
|
|||
from zeep import Client
|
||||
from zeep.cache import InMemoryCache
|
||||
from zeep.exceptions import Error as ZeepError
|
||||
from zeep.exceptions import Fault, TransportError
|
||||
from zeep.exceptions import Fault, TransportError, ValidationError
|
||||
from zeep.proxy import OperationProxy, ServiceProxy
|
||||
from zeep.transports import Transport
|
||||
|
||||
|
@ -62,6 +62,11 @@ class SOAPFault(SOAPError):
|
|||
)
|
||||
|
||||
|
||||
class SOAPValidationError(SOAPError):
|
||||
log_error = False
|
||||
http_status = 400
|
||||
|
||||
|
||||
class OperationProxyWrapper(OperationProxy):
|
||||
def __call__(self, *args, **kwargs):
|
||||
client = self._proxy._client
|
||||
|
@ -71,6 +76,8 @@ class OperationProxyWrapper(OperationProxy):
|
|||
raise SOAPServiceUnreachable(client, transport_error)
|
||||
except Fault as fault:
|
||||
raise SOAPFault(client, fault)
|
||||
except ValidationError as validation_error:
|
||||
raise SOAPValidationError(validation_error)
|
||||
except ZeepError as zeep_error:
|
||||
raise SOAPError(str(zeep_error))
|
||||
|
||||
|
|
|
@ -5,12 +5,11 @@ from unittest import mock
|
|||
|
||||
import pytest
|
||||
from django.utils.encoding import force_str
|
||||
from zeep.exceptions import Fault as WebFault
|
||||
from zeep.exceptions import TransportError
|
||||
|
||||
from passerelle.contrib.dpark.models import DPark, Pairing
|
||||
from passerelle.utils.conversion import to_pdf
|
||||
from passerelle.utils.jsonresponse import APIError
|
||||
from passerelle.utils.soap import SOAPError
|
||||
from tests.utils import ResponsesSoap, make_resource
|
||||
|
||||
SLUG = 'test'
|
||||
|
@ -71,10 +70,6 @@ class ReplyDataClass(dict):
|
|||
super().__init__(**kwargs)
|
||||
|
||||
|
||||
class WebFaultHavingLatin1(WebFault):
|
||||
pass
|
||||
|
||||
|
||||
class MockedService:
|
||||
def __init__(self, success=True, error_class=None, replydata=None):
|
||||
self.success = success
|
||||
|
@ -82,20 +77,14 @@ class MockedService:
|
|||
self.replydata = replydata
|
||||
|
||||
def raise_error(self):
|
||||
if self.error_class is WebFault:
|
||||
raise self.error_class(mock.Mock(faulstring='Error %s raised' % self.error_class.__name__), None)
|
||||
if self.error_class is TransportError:
|
||||
raise self.error_class('connection error occured', None)
|
||||
if self.error_class is WebFaultHavingLatin1:
|
||||
raise WebFault(message='éêè')
|
||||
raise Exception('random error')
|
||||
if self.error_class:
|
||||
raise self.error_class
|
||||
|
||||
def return_response(self, *args, **kwargs):
|
||||
return ReplyDataClass(**self.replydata)
|
||||
|
||||
def __getattr__(self, name):
|
||||
if self.error_class:
|
||||
self.raise_error()
|
||||
self.raise_error()
|
||||
return self.return_response
|
||||
|
||||
|
||||
|
@ -106,18 +95,9 @@ def get_service():
|
|||
|
||||
|
||||
def test_call_service_error(dpark, app, get_service):
|
||||
get_service.return_value = MockedService(error_class=WebFault)
|
||||
get_service.return_value = MockedService(error_class=SOAPError('boom!'))
|
||||
resp = app.get('/dpark/test/ping/')
|
||||
assert 'ServiceError: ' in resp.json['err_desc']
|
||||
get_service.return_value = MockedService(error_class=TransportError)
|
||||
resp = app.get('/dpark/test/ping/')
|
||||
assert 'Error: connection error occured' in resp.json['err_desc']
|
||||
get_service.return_value = MockedService(error_class=Exception)
|
||||
resp = app.get('/dpark/test/ping/')
|
||||
assert 'Error: random error' in resp.json['err_desc']
|
||||
get_service.return_value = MockedService(error_class=WebFaultHavingLatin1)
|
||||
resp = app.get('/dpark/test/ping/')
|
||||
assert 'ServiceError: éêè' in resp.json['err_desc']
|
||||
assert 'boom!' in resp.json['err_desc']
|
||||
|
||||
|
||||
def test_ping(dpark, app, get_service):
|
||||
|
|
|
@ -307,7 +307,7 @@ def test_say_hello_method_validation_error(connector, soap, app):
|
|||
resp = app.get('/soap/test/method/sayHello/')
|
||||
assert resp.json == {
|
||||
"err": 1,
|
||||
"err_class": "passerelle.utils.soap.SOAPError",
|
||||
"err_class": "passerelle.utils.soap.SOAPValidationError",
|
||||
"err_desc": soap.VALIDATION_ERROR,
|
||||
"data": None,
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue