From 2049f6346920aa893177467dd852c7ef7164fd21 Mon Sep 17 00:00:00 2001 From: Benjamin Dauvergne Date: Mon, 6 Jun 2016 10:07:41 +0200 Subject: [PATCH] add query string parameters to webservice call action --- help/fr/wf-wscall.page | 9 ++++++++ tests/test_workflows.py | 23 ++++++++++++++++++++ wcs/wf/wscall.py | 58 +++++++++++++++++++++++++++++++++++++++++-------- 3 files changed, 81 insertions(+), 9 deletions(-) diff --git a/help/fr/wf-wscall.page b/help/fr/wf-wscall.page index d737831..4317881 100644 --- a/help/fr/wf-wscall.page +++ b/help/fr/wf-wscall.page @@ -29,6 +29,15 @@ par exemple transmettre une information particulière.

+Le tableau « Données à envoyer en paramètre » permet de décrire des données qui +seront transmises sous la forme de paramètres d'URL. Sur chaque ligne, la +colonne de gauche est le nom de la clé, celle de droite la valeur. La valeur +peut être une expression Python, pour cela elle doit commencer par le signe +« = ». Les paramètres d'URL ne peuvent être que des chaînes si ce n'est pas le +cas la donnée sera transformée en chaîne de force. +

+ +

La case à cocher « Envoyer le formulaire (POST, en JSON) » indique que l'ensemble des données du formulaire doivent être transmises, avec un appel de type POST, dont le contenu correspondra au formulaire encodé au diff --git a/tests/test_workflows.py b/tests/test_workflows.py index 66bee97..7ee09cb 100644 --- a/tests/test_workflows.py +++ b/tests/test_workflows.py @@ -3,6 +3,7 @@ import pytest import shutil import time import urllib2 +import urlparse import mock @@ -849,6 +850,28 @@ def test_webservice_call(pub): rendered = formdata.evolution[-1].parts[-1].view() assert 'Error during webservice call "do that"' in str(rendered) + item = WebserviceCallStatusItem() + item.method = 'GET' + item.post = False + item.url = 'http://remote.example.net?in_url=1' + item.qs_data = { + 'str': 'abcd', + 'one': '=1', + 'evalme': '=form_number', + 'error': '=1=3', + 'in_url': '2', + } + pub.substitutions.feed(formdata) + item.perform(formdata) + assert http_requests.get_last('method') == 'GET' + qs = urlparse.parse_qs(http_requests.get_last('url').split('?')[1]) + assert set(qs.keys()) == set(['in_url', 'str', 'one', 'evalme']) + assert qs['in_url'] == ['1', '2'] + assert qs['one'] == ['1'] + assert qs['evalme'] == [formdata.get_display_id()] + assert qs['str'] == ['abcd'] + + def test_timeout(pub): workflow = Workflow(name='timeout') st1 = workflow.add_status('Status1', 'st1') diff --git a/wcs/wf/wscall.py b/wcs/wf/wscall.py index 1765210..1f9eba6 100644 --- a/wcs/wf/wscall.py +++ b/wcs/wf/wscall.py @@ -22,6 +22,9 @@ import xml.etree.ElementTree as ET import collections import mimetypes from StringIO import StringIO +import urllib +import urlparse + from quixote.html import TemplateIO, htmltext from qommon.errors import ConnectionError @@ -103,6 +106,7 @@ class WebserviceCallStatusItem(WorkflowStatusItem): post = True request_signature_key = None post_data = None + qs_data = None _method = None response_type = 'json' @@ -135,7 +139,8 @@ class WebserviceCallStatusItem(WorkflowStatusItem): 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', - 'record_errors', 'label', 'method', 'response_type') + 'record_errors', 'label', 'method', 'response_type', + 'qs_data') def add_parameters_widgets(self, form, parameters, prefix='', formdef=None): if 'label' in parameters: @@ -150,6 +155,11 @@ class WebserviceCallStatusItem(WorkflowStatusItem): form.add(ComputedExpressionWidget, '%srequest_signature_key' % prefix, title=_('Request Signature Key'), value=self.request_signature_key) + if 'qs_data' in parameters: + form.add(WidgetDict, '%sqs_data' % prefix, + title=_('Query string data'), + value=self.qs_data or {}, + element_value_type=ComputedExpressionWidget) methods = collections.OrderedDict( [('GET', _('GET')), ('POST', _('POST (JSON)'))]) if 'method' in parameters: @@ -234,6 +244,23 @@ class WebserviceCallStatusItem(WorkflowStatusItem): variables = get_publisher().substitutions.get_context_variables() url = get_variadic_url(url, variables) + if self.qs_data: # merge qs_data into url + publisher = get_publisher() + parsed = urlparse.urlparse(url) + qs = list(urlparse.parse_qsl(parsed.query)) + for key, value in self.qs_data.iteritems(): + try: + value = self.compute(value, raises=True) + except: + get_publisher().notify_of_exception(sys.exc_info()) + else: + key = publisher.sitecharset2utf8(key) + value = str(value) + value = publisher.sitecharset2utf8(value) + qs.append((key, value)) + qs = urllib.urlencode(qs) + url = urlparse.urlunparse(parsed[:4] + (qs,) + parsed[5:6]) + if self.request_signature_key: signature_key = self.compute(self.request_signature_key) if signature_key: @@ -372,11 +399,12 @@ class WebserviceCallStatusItem(WorkflowStatusItem): def get_jump_label(self): return _('Error calling webservice') - def post_data_export_to_xml(self, xml_item, charset, include_id=False): - if not self.post_data: + def _kv_data_export_to_xml(self, xml_item, charset, include_id, attribute): + assert attribute + if not getattr(self, attribute): return - el = ET.SubElement(xml_item, 'post_data') - for (key, value) in self.post_data.items(): + el = ET.SubElement(xml_item, attribute) + for (key, value) in getattr(self, attribute).items(): item = ET.SubElement(el, 'item') if type(key) is unicode: ET.SubElement(item, 'name').text = key @@ -391,14 +419,26 @@ class WebserviceCallStatusItem(WorkflowStatusItem): else: raise AssertionError('unknown type for value (%r)' % key) - - def post_data_init_with_xml(self, elem, charset, include_id=False): + def _kv_data_init_with_xml(self, elem, charset, include_id, attribute): if elem is None: return - self.post_data = {} + setattr(self, attribute, {}) for item in elem.findall('item'): key = item.find('name').text.encode(charset) value = item.find('value').text.encode(charset) - self.post_data[key] = value + getattr(self, attribute)[key] = value + + def post_data_export_to_xml(self, xml_item, charset, include_id=False): + self._kv_data_export_to_xml(self, xml_item, charset, include_id=include_id, + attribute='post_data') + + def post_data_init_with_xml(self, elem, charset, include_id=False): + self._kv_data_init_with_xml(elem, charset, include_id=include_id, attribute='post_data') + + def qs_data_export_to_xml(self, xml_item, charset, include_id=False): + self._kv_data_export_to_xml(xml_item, charset, include_id=include_id, attribute='qs_data') + + def qs_data_init_with_xml(self, elem, charset, include_id=False): + self._kv_data_init_with_xml(element, charset, include_id=include_id, attribute='qs_data') register_item_class(WebserviceCallStatusItem) -- 2.1.4