wscall: add parameters to add elements to query string (#11207)

This commit is contained in:
Benjamin Dauvergne 2016-06-06 10:07:41 +02:00 committed by Frédéric Péters
parent 0f4809b388
commit fe688437e0
4 changed files with 83 additions and 9 deletions

View File

@ -28,6 +28,15 @@ par exemple transmettre une information particulière.
<code>https://www.example.net/notify?email=[session_user_email]</code> <code>https://www.example.net/notify?email=[session_user_email]</code>
</example> </example>
<p>
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.
</p>
<p> <p>
La case à cocher « Envoyer le formulaire (POST, en JSON) » indique que 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 l'ensemble des données du formulaire doivent être transmises, avec un appel de

View File

@ -308,6 +308,7 @@ def test_wscall_action():
wscall.post = False wscall.post = False
wscall.request_signature_key = 'key' wscall.request_signature_key = 'key'
wscall.post_data = {'one': '1', 'two': '=2', 'good:name': 'ok'} wscall.post_data = {'one': '1', 'two': '=2', 'good:name': 'ok'}
wscall.qs_data = {'one': '2', 'two': '=3', 'good:name': 'ok'}
st1.items.append(wscall) st1.items.append(wscall)
wscall.parent = st1 wscall.parent = st1
@ -318,6 +319,7 @@ def test_wscall_action():
assert wscall2.post == False assert wscall2.post == False
assert wscall2.request_signature_key == 'key' assert wscall2.request_signature_key == 'key'
assert wscall2.post_data == {'one': '1', 'two': '=2', 'good:name': 'ok'} assert wscall2.post_data == {'one': '1', 'two': '=2', 'good:name': 'ok'}
assert wscall2.qs_data == {'one': '2', 'two': '=3', 'good:name': 'ok'}
def test_backoffice_info_text(): def test_backoffice_info_text():
wf = Workflow(name='info texts') wf = Workflow(name='info texts')

View File

@ -3,6 +3,7 @@ import pytest
import shutil import shutil
import time import time
import urllib2 import urllib2
import urlparse
import mock import mock
@ -849,6 +850,28 @@ def test_webservice_call(pub):
rendered = formdata.evolution[-1].parts[-1].view() rendered = formdata.evolution[-1].parts[-1].view()
assert 'Error during webservice call &quot;do that&quot;' in str(rendered) assert 'Error during webservice call &quot;do that&quot;' 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): def test_timeout(pub):
workflow = Workflow(name='timeout') workflow = Workflow(name='timeout')
st1 = workflow.add_status('Status1', 'st1') st1 = workflow.add_status('Status1', 'st1')

View File

@ -22,6 +22,9 @@ import xml.etree.ElementTree as ET
import collections import collections
import mimetypes import mimetypes
from StringIO import StringIO from StringIO import StringIO
import urllib
import urlparse
from quixote.html import TemplateIO, htmltext from quixote.html import TemplateIO, htmltext
from qommon.errors import ConnectionError from qommon.errors import ConnectionError
@ -103,6 +106,7 @@ class WebserviceCallStatusItem(WorkflowStatusItem):
post = True post = True
request_signature_key = None request_signature_key = None
post_data = None post_data = None
qs_data = None
_method = None _method = None
response_type = 'json' response_type = 'json'
@ -135,7 +139,8 @@ class WebserviceCallStatusItem(WorkflowStatusItem):
return ('url', 'post', 'varname', 'request_signature_key', 'post_data', return ('url', 'post', 'varname', 'request_signature_key', 'post_data',
'action_on_4xx', 'action_on_5xx', 'action_on_bad_data', 'action_on_4xx', 'action_on_5xx', 'action_on_bad_data',
'action_on_network_errors', 'notify_on_errors', '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): def add_parameters_widgets(self, form, parameters, prefix='', formdef=None):
if 'label' in parameters: if 'label' in parameters:
@ -150,6 +155,11 @@ class WebserviceCallStatusItem(WorkflowStatusItem):
form.add(ComputedExpressionWidget, '%srequest_signature_key' % prefix, form.add(ComputedExpressionWidget, '%srequest_signature_key' % prefix,
title=_('Request Signature Key'), title=_('Request Signature Key'),
value=self.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( methods = collections.OrderedDict(
[('GET', _('GET')), ('POST', _('POST (JSON)'))]) [('GET', _('GET')), ('POST', _('POST (JSON)'))])
if 'method' in parameters: if 'method' in parameters:
@ -234,6 +244,23 @@ class WebserviceCallStatusItem(WorkflowStatusItem):
variables = get_publisher().substitutions.get_context_variables() variables = get_publisher().substitutions.get_context_variables()
url = get_variadic_url(url, 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)
value = str(value)
except:
get_publisher().notify_of_exception(sys.exc_info())
else:
key = publisher.sitecharset2utf8(key)
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: if self.request_signature_key:
signature_key = self.compute(self.request_signature_key) signature_key = self.compute(self.request_signature_key)
if signature_key: if signature_key:
@ -372,11 +399,12 @@ class WebserviceCallStatusItem(WorkflowStatusItem):
def get_jump_label(self): def get_jump_label(self):
return _('Error calling webservice') return _('Error calling webservice')
def post_data_export_to_xml(self, xml_item, charset, include_id=False): def _kv_data_export_to_xml(self, xml_item, charset, include_id, attribute):
if not self.post_data: assert attribute
if not getattr(self, attribute):
return return
el = ET.SubElement(xml_item, 'post_data') el = ET.SubElement(xml_item, attribute)
for (key, value) in self.post_data.items(): for (key, value) in getattr(self, attribute).items():
item = ET.SubElement(el, 'item') item = ET.SubElement(el, 'item')
if type(key) is unicode: if type(key) is unicode:
ET.SubElement(item, 'name').text = key ET.SubElement(item, 'name').text = key
@ -391,14 +419,26 @@ class WebserviceCallStatusItem(WorkflowStatusItem):
else: else:
raise AssertionError('unknown type for value (%r)' % key) raise AssertionError('unknown type for value (%r)' % key)
def _kv_data_init_with_xml(self, elem, charset, include_id, attribute):
def post_data_init_with_xml(self, elem, charset, include_id=False):
if elem is None: if elem is None:
return return
self.post_data = {} setattr(self, attribute, {})
for item in elem.findall('item'): for item in elem.findall('item'):
key = item.find('name').text.encode(charset) key = item.find('name').text.encode(charset)
value = item.find('value').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(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(elem, charset, include_id=include_id, attribute='qs_data')
register_item_class(WebserviceCallStatusItem) register_item_class(WebserviceCallStatusItem)