From 4b8c7ca759ed7455458db0e4d58745e793419cbf Mon Sep 17 00:00:00 2001 From: Thomas NOEL Date: Wed, 24 Aug 2016 17:34:01 +0200 Subject: [PATCH] wscall: add action if err in json data or specific header (#12916) --- tests/test_workflows.py | 100 ++++++++++++++++++++++++++++++++++++++++++++++++ tests/utilities.py | 8 ++++ wcs/wf/wscall.py | 31 ++++++++++++--- 3 files changed, 134 insertions(+), 5 deletions(-) diff --git a/tests/test_workflows.py b/tests/test_workflows.py index b5a1d51..b7ddebe 100644 --- a/tests/test_workflows.py +++ b/tests/test_workflows.py @@ -728,6 +728,84 @@ def test_webservice_call(pub): formdata.workflow_data = None item = WebserviceCallStatusItem() + item.url = 'http://remote.example.net/json-err0' + item.post = False + item.varname = 'xxx' + item.perform(formdata) + assert formdata.workflow_data['xxx_status'] == 200 + assert formdata.workflow_data['xxx_response'] == {'data': 'foo', 'err': 0} + assert formdata.workflow_data.get('xxx_time') + formdata.workflow_data = None + + item = WebserviceCallStatusItem() + item.url = 'http://remote.example.net/json-err0' + item.post = False + item.varname = 'xxx' + item.action_on_error_code = ':stop' + item.perform(formdata) + assert formdata.workflow_data['xxx_status'] == 200 + assert formdata.workflow_data['xxx_response'] == {'data': 'foo', 'err': 0} + assert formdata.workflow_data.get('xxx_time') + formdata.workflow_data = None + + item = WebserviceCallStatusItem() + item.url = 'http://remote.example.net/json-err1' + item.post = False + item.varname = 'xxx' + item.perform(formdata) + assert formdata.workflow_data['xxx_status'] == 200 + assert formdata.workflow_data['xxx_response'] == {'data': '', 'err': 1} + assert formdata.workflow_data.get('xxx_time') + formdata.workflow_data = None + + item = WebserviceCallStatusItem() + item.url = 'http://remote.example.net/json-err1' + item.post = False + item.varname = 'xxx' + item.action_on_error_code = ':stop' + with pytest.raises(AbortActionException): + item.perform(formdata) + assert formdata.workflow_data['xxx_status'] == 200 + assert formdata.workflow_data['xxx_error_response'] == {'data': '', 'err': 1} + assert formdata.workflow_data.get('xxx_time') + formdata.workflow_data = None + + item = WebserviceCallStatusItem() + item.url = 'http://remote.example.net/json-errheader0' + item.post = False + item.varname = 'xxx' + item.perform(formdata) + assert formdata.workflow_data['xxx_status'] == 200 + assert formdata.workflow_data['xxx_error_header'] == 0 + assert formdata.workflow_data['xxx_response'] == {'foo': 'bar'} + assert formdata.workflow_data.get('xxx_time') + formdata.workflow_data = None + + item = WebserviceCallStatusItem() + item.url = 'http://remote.example.net/json-errheader1' + item.post = False + item.varname = 'xxx' + item.perform(formdata) + assert formdata.workflow_data['xxx_status'] == 200 + assert formdata.workflow_data['xxx_error_header'] == 1 + assert formdata.workflow_data['xxx_error_response'] == {'foo': 'bar'} + assert formdata.workflow_data.get('xxx_time') + formdata.workflow_data = None + + item = WebserviceCallStatusItem() + item.url = 'http://remote.example.net/json-errheader1' + item.post = False + item.varname = 'xxx' + item.action_on_error_code = ':stop' + with pytest.raises(AbortActionException): + item.perform(formdata) + assert formdata.workflow_data['xxx_status'] == 200 + assert formdata.workflow_data['xxx_error_header'] == 1 + assert formdata.workflow_data['xxx_error_response'] == {'foo': 'bar'} + assert formdata.workflow_data.get('xxx_time') + formdata.workflow_data = None + + item = WebserviceCallStatusItem() item.url = 'http://remote.example.net' item.post = False item.request_signature_key = 'xxx' @@ -868,6 +946,28 @@ def test_webservice_call(pub): formdata.workflow_data = None item = WebserviceCallStatusItem() + item.url = 'http://remote.example.net/xml-errheader' + item.post = False + item.varname = 'xxx' + item.response_type = 'attachment' + item.record_errors = True + item.perform(formdata) + assert formdata.workflow_data.get('xxx_status') == 200 + assert formdata.workflow_data.get('xxx_error_header') == 1 + + item = WebserviceCallStatusItem() + item.url = 'http://remote.example.net/xml-errheader' + item.post = False + item.varname = 'xxx' + item.response_type = 'attachment' + item.record_errors = True + item.action_on_error_code = ':stop' + with pytest.raises(AbortActionException): + item.perform(formdata) + assert formdata.workflow_data.get('xxx_status') == 200 + assert formdata.workflow_data.get('xxx_error_header') == 1 + + item = WebserviceCallStatusItem() item.url = 'http://remote.example.net/400-json' item.post = False item.record_errors = True diff --git a/tests/utilities.py b/tests/utilities.py index cf085c4..a2c6dea 100644 --- a/tests/utilities.py +++ b/tests/utilities.py @@ -250,8 +250,16 @@ class HttpRequestsMocking(object): 'http://remote.example.net/404-json': (404, '{"err": 1}', None), 'http://remote.example.net/500': (500, 'internal server error', None), 'http://remote.example.net/json': (200, '{"foo": "bar"}', None), + 'http://remote.example.net/json-err0': (200, '{"data": "foo", "err": 0}', None), + 'http://remote.example.net/json-err1': (200, '{"data": "", "err": 1}', None), + 'http://remote.example.net/json-errheader0': (200, '{"foo": "bar"}', + {'x-passerelle-err': '0'}), + 'http://remote.example.net/json-errheader1': (200, '{"foo": "bar"}', + {'x-passerelle-err': '1'}), 'http://remote.example.net/xml': (200, '', {'content-type': 'text/xml'}), + 'http://remote.example.net/xml-errheader': (200, '', + {'content-type': 'text/xml', 'x-passerelle-err': '1'}), }.get(base_url, (200, '', {})) class FakeResponse(object): diff --git a/wcs/wf/wscall.py b/wcs/wf/wscall.py index 2e8228b..02e6d3c 100644 --- a/wcs/wf/wscall.py +++ b/wcs/wf/wscall.py @@ -109,6 +109,7 @@ class WebserviceCallStatusItem(WorkflowStatusItem): action_on_5xx = ':stop' action_on_bad_data = ':pass' action_on_network_errors = ':stop' + action_on_error_code = ':pass' notify_on_errors = True record_errors = False @@ -133,7 +134,7 @@ class WebserviceCallStatusItem(WorkflowStatusItem): def get_parameters(self): return ('url', 'post', 'varname', 'request_signature_key', 'post_data', 'action_on_4xx', 'action_on_5xx', 'action_on_bad_data', - 'action_on_network_errors', 'notify_on_errors', + 'action_on_network_errors', 'action_on_error_code', 'notify_on_errors', 'record_errors', 'label', 'method', 'response_type', 'qs_data') @@ -199,7 +200,7 @@ class WebserviceCallStatusItem(WorkflowStatusItem): error_actions.extend([(x.id, _('Jump to %s') % x.name) for x in self.parent.parent.possible_status]) for attribute in ('action_on_4xx', 'action_on_5xx', 'action_on_network_errors', - 'action_on_bad_data'): + 'action_on_bad_data', 'action_on_error_code'): if not attribute in parameters: continue if attribute == 'action_on_bad_data': @@ -213,7 +214,8 @@ class WebserviceCallStatusItem(WorkflowStatusItem): 'action_on_4xx': _('Action on HTTP error 4xx'), 'action_on_5xx': _('Action on HTTP error 5xx'), 'action_on_bad_data': _('Action on non-JSON response'), - 'action_on_network_errors': _('Action on network errors') + 'action_on_network_errors': _('Action on network errors'), + 'action_on_error_code': _('Action on JSON or header error'), }.get(attribute) form.add(SingleSelectWidget, '%s%s' % (prefix, attribute), title=label, @@ -249,14 +251,25 @@ class WebserviceCallStatusItem(WorkflowStatusItem): self.action_on_error(self.action_on_network_errors, formdata, exc_info=sys.exc_info()) + error_code = 0 + error_code_header = response.getheader('x-passerelle-err') + if error_code_header: + # result is good only if header value is '0' + try: + error_code = int(error_code_header) + except ValueError as e: + error_code = error_code_header + if self.varname: workflow_data = { '%s_status' % self.varname: status, '%s_time' % self.varname: datetime.datetime.now().isoformat(), } + if error_code_header: + workflow_data['%s_error_header' % self.varname] = error_code if status in (204, 205): pass # not returning any content - elif (status // 100) == 2: + elif (status // 100) == 2 and error_code == 0: self.store_response(formdata, response, data, workflow_data) else: # on error, record data if it is JSON try: @@ -268,6 +281,8 @@ class WebserviceCallStatusItem(WorkflowStatusItem): formdata.update_workflow_data(workflow_data) formdata.store() + if error_code != 0: + self.action_on_error(self.action_on_error_code, formdata, response, data=data) if (status // 100) == 4: self.action_on_error(self.action_on_4xx, formdata, response, data=data) if (status // 100) == 5: @@ -283,6 +298,12 @@ class WebserviceCallStatusItem(WorkflowStatusItem): self.action_on_error(self.action_on_bad_data, formdata, response, data=data, exc_info=sys.exc_info()) else: + if d.get('err'): + workflow_data['%s_error_response' % self.varname] = d + formdata.update_workflow_data(workflow_data) + formdata.store() + self.action_on_error(self.action_on_error_code, formdata, + response, data=data) workflow_data['%s_response' % self.varname] = d if isinstance(d.get('data'), dict) and d['data'].get('display_id'): formdata.id_display = d.get('data', {}).get('display_id') @@ -332,7 +353,7 @@ class WebserviceCallStatusItem(WorkflowStatusItem): def get_target_status(self): targets = [] for attribute in ('action_on_4xx', 'action_on_5xx', 'action_on_bad_data', - 'action_on_network_errors'): + 'action_on_network_errors', 'action_on_error_code'): value = getattr(self, attribute) if value in (':pass', ':stop'): continue -- 2.9.3