workflows: log invalid payload in webservice calls (#74150) #713
|
@ -89,3 +89,19 @@ def test_wscall_record_errors(pub):
|
|||
'label': None,
|
||||
'data_b64': '8Q==\n',
|
||||
}
|
||||
|
||||
# error with payload that cannot be converted to JSON
|
||||
pub.loggederror_class.wipe()
|
||||
formdata.evolution[-1].parts = []
|
||||
formdata.store()
|
||||
wscall.method = 'POST'
|
||||
wscall.post_data = {'xxx': '=Ellipsis'}
|
||||
wscall.perform(formdata)
|
||||
assert pub.loggederror_class.count() == 1
|
||||
assert (
|
||||
formdata.workflow_data['varname_payload_error'] == 'Object of type ellipsis is not JSON serializable'
|
||||
)
|
||||
assert (
|
||||
pub.loggederror_class.select()[0].summary
|
||||
== 'Invalid payload (Object of type ellipsis is not JSON serializable)'
|
||||
)
|
||||
|
|
|
@ -34,7 +34,7 @@ from wcs.workflows import (
|
|||
WorkflowStatusItem,
|
||||
register_item_class,
|
||||
)
|
||||
from wcs.wscalls import call_webservice, get_app_error_code
|
||||
from wcs.wscalls import PayloadError, call_webservice, get_app_error_code
|
||||
|
||||
from ..qommon import _, force_str, pgettext
|
||||
from ..qommon.errors import ConnectionError
|
||||
|
@ -461,6 +461,19 @@ class WebserviceCallStatusItem(WorkflowStatusItem):
|
|||
formdata.store()
|
||||
self.action_on_error(self.action_on_network_errors, formdata, exception=e)
|
||||
return
|
||||
except PayloadError as e:
|
||||
if self.varname:
|
||||
workflow_data['%s_payload_error' % self.varname] = str(e)
|
||||
formdata.update_workflow_data(workflow_data)
|
||||
formdata.store()
|
||||
# always log errors from our side
|
||||
get_publisher().record_error(
|
||||
_('Invalid payload (%s)') % str(e),
|
||||
formdata=formdata,
|
||||
status_item=self,
|
||||
exception=e,
|
||||
)
|
||||
return
|
||||
|
||||
|
||||
app_error_code = get_app_error_code(response, data, self.response_type)
|
||||
app_error_code_header = response.headers.get('x-error-code')
|
||||
|
|
|
@ -44,6 +44,10 @@ from .qommon.template import Template
|
|||
from .qommon.xml_storage import XmlStorableObject
|
||||
|
||||
|
||||
class PayloadError(Exception):
|
||||
pass
|
||||
|
||||
|
||||
def get_app_error_code(response, data, response_type):
|
||||
app_error_code = 0
|
||||
app_error_code_header = response.headers.get('x-error-code')
|
||||
|
@ -174,7 +178,13 @@ def call_webservice(
|
|||
if method in ('PATCH', 'PUT', 'POST', 'DELETE'):
|
||||
if payload:
|
||||
headers['Content-type'] = 'application/json'
|
||||
payload = json.dumps(payload, cls=JSONEncoder)
|
||||
try:
|
||||
payload = json.dumps(payload, cls=JSONEncoder)
|
||||
except TypeError as e:
|
||||
get_publisher().record_error(
|
||||
exception=e, context='[WSCALL]', notify=notify_on_errors, record=record_on_errors
|
||||
)
|
||||
raise PayloadError(str(e)) from e
|
||||
response, status, data, dummy = misc._http_request(method=method, body=payload, **request_kwargs)
|
||||
else:
|
||||
response, status, data, dummy = misc.http_get_page(**request_kwargs)
|
||||
|
|
Loading…
Reference in New Issue
J'ai hésité à ajouter une gestion d'erreur particulière ici, comme on a pour les erreurs HTTP du webservice mais j'ai finalement décidé que non, comme une action "données de traitement" qui foirerait, l'enregistrement de l'erreur suffit.