From e45d04d51ab9578ab5773c8b374b3f9d9de823b6 Mon Sep 17 00:00:00 2001 From: Thomas NOEL Date: Mon, 31 Aug 2015 17:42:41 +0200 Subject: [PATCH] wscall: allow extra data on POST (#6622) --- tests/test_workflows.py | 28 ++++++++++++++++++++++++++++ wcs/wf/wscall.py | 39 +++++++++++++++++++++++++++++++++------ wcs/workflows.py | 4 +++- 3 files changed, 64 insertions(+), 7 deletions(-) diff --git a/tests/test_workflows.py b/tests/test_workflows.py index 9007235..03134bf 100644 --- a/tests/test_workflows.py +++ b/tests/test_workflows.py @@ -400,6 +400,9 @@ def test_webservice_call(pub): item.perform(formdata) assert http_requests.get_last('url') == 'http://remote.example.net' assert http_requests.get_last('method') == 'POST' + payload = json.loads(http_requests.get_last('body')) + assert payload['url'].startswith('http://example.net/baz-') + assert int(payload['display_id']) == 1 item = WebserviceCallStatusItem() item.url = 'http://remote.example.net' @@ -411,6 +414,31 @@ def test_webservice_call(pub): item = WebserviceCallStatusItem() item.url = 'http://remote.example.net' item.post = False + item.post_data = {'str': 'abcd', 'one': '=1', + 'evalme': '=form_number', 'error':'=1=3'} + pub.substitutions.feed(formdata) + item.perform(formdata) + assert http_requests.get_last('url') == 'http://remote.example.net' + assert http_requests.get_last('method') == 'POST' + payload = json.loads(http_requests.get_last('body')) + assert payload == {'one': 1, 'str': 'abcd', 'evalme': formdata.id} + + item = WebserviceCallStatusItem() + item.url = 'http://remote.example.net' + item.post_data = {'str': 'abcd', 'one': '=1', + 'evalme': '=form_number', 'error':'=1=3'} + pub.substitutions.feed(formdata) + item.perform(formdata) + assert http_requests.get_last('url') == 'http://remote.example.net' + assert http_requests.get_last('method') == 'POST' + payload = json.loads(http_requests.get_last('body')) + assert payload['extra'] == {'one': 1, 'str': 'abcd', 'evalme': formdata.id} + assert payload['url'].startswith('http://example.net/baz-') + assert int(payload['display_id']) == 1 + + item = WebserviceCallStatusItem() + item.url = 'http://remote.example.net' + item.post = False item.request_signature_key = 'xxx' item.perform(formdata) assert 'signature=' in http_requests.get_last('url') diff --git a/wcs/wf/wscall.py b/wcs/wf/wscall.py index 9f72c41..6b1341f 100644 --- a/wcs/wf/wscall.py +++ b/wcs/wf/wscall.py @@ -15,9 +15,10 @@ # along with this program; if not, see . import json +import sys from qommon.form import * -from qommon.misc import http_get_page, http_post_request, get_variadic_url +from qommon.misc import http_get_page, http_post_request, get_variadic_url, JSONEncoder from wcs.workflows import WorkflowStatusItem, register_item_class, template_on_formdata from wcs.api import sign_url @@ -32,9 +33,10 @@ class WebserviceCallStatusItem(WorkflowStatusItem): varname = None post = True request_signature_key = None + post_data = None def get_parameters(self): - return ('url', 'post', 'varname', 'request_signature_key') + return ('url', 'post', 'varname', 'request_signature_key', 'post_data') def add_parameters_widgets(self, form, parameters, prefix='', formdef=None): if 'url' in parameters: @@ -45,10 +47,14 @@ class WebserviceCallStatusItem(WorkflowStatusItem): form.add(CheckboxWidget, '%spost' % prefix, title=_('Post formdata (JSON)'), value=self.post) + if 'post_data' in parameters: + form.add(WidgetDict, '%spost_data' % prefix, + title=_('Post data'), + value=self.post_data or {}) if 'varname' in parameters: form.add(VarnameWidget, '%svarname' % prefix, title=_('Variable Name'), value=self.varname) - if 'request_signature_key': + if 'request_signature_key' in parameters: form.add(StringWidget, '%srequest_signature_key' % prefix, title=_('Request Signature Key'), value=self.request_signature_key) @@ -69,13 +75,34 @@ class WebserviceCallStatusItem(WorkflowStatusItem): headers = {'Content-type': 'application/json', 'Accept': 'application/json'} + post_data = None # payload + + # if self.post_data exists, post_data is a dict built from it + if self.post_data: + post_data = {} + for (key, value) in self.post_data.items(): + try: + post_data[key] = self.compute(value, raises=True) + except: + get_publisher().notify_of_exception(sys.exc_info()) + + # if formdata has to be sent, it's the payload. If post_data exists, + # it's added in formdata['extra'] if self.post: - formdata_as_json = formdata.export_to_json() - response, status, data, auth_header = http_post_request( - url, formdata_as_json, headers=headers, timeout=TIMEOUT) + formdata_dict = formdata.get_json_export_dict() + if post_data is not None: + formdata_dict['extra'] = post_data + post_data = formdata_dict + + if post_data is not None: + post_data = json.dumps(post_data, cls=JSONEncoder, + encoding=get_publisher().site_charset) + response, status, data, authheader = http_post_request( + url, post_data, headers=headers, timeout=TIMEOUT) else: response, status, data, auth_header = http_get_page( url, headers=headers, timeout=TIMEOUT) + if self.varname: workflow_data = {'%s_status' % self.varname: status} if status == 200: diff --git a/wcs/workflows.py b/wcs/workflows.py index a1ca87a..ecfdd3a 100644 --- a/wcs/workflows.py +++ b/wcs/workflows.py @@ -836,7 +836,7 @@ class WorkflowStatusItem(object): value = getattr(self, '%s_parse' % f)(value) setattr(self, f, value) - def compute(self, var): + def compute(self, var, raises=False): if not isinstance(var, basestring): return var if not var.startswith('='): @@ -845,6 +845,8 @@ class WorkflowStatusItem(object): try: return eval(var[1:], get_publisher().get_global_eval_dict(), vars) except: + if raises: + raise return var def get_substitution_variables(self, formdata): -- 2.5.0