wscalls: implement PUT, PATCH and DELETE verbs (#12416)

This commit is contained in:
Benjamin Dauvergne 2016-07-02 18:44:13 +02:00 committed by Frédéric Péters
parent 8f9dc0523d
commit c5f786d222
4 changed files with 91 additions and 11 deletions

View File

@ -1482,6 +1482,40 @@ def test_webservice_call(http_requests, pub):
assert qs['ezt'] == [formdata.get_display_id()]
assert qs['str'] == ['abcd']
item = WebserviceCallStatusItem()
item.method = 'DELETE'
item.post = False
item.url = 'http://remote.example.net/json'
pub.substitutions.feed(formdata)
item.perform(formdata)
assert http_requests.get_last('method') == 'DELETE'
item = WebserviceCallStatusItem()
item.url = 'http://remote.example.net'
item.method = 'PUT'
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') == 'PUT'
payload = json.loads(http_requests.get_last('body'))
assert payload == {'one': 1, 'str': 'abcd', 'evalme': formdata.get_display_id()}
item = WebserviceCallStatusItem()
item.url = 'http://remote.example.net'
item.method = 'PATCH'
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') == 'PATCH'
payload = json.loads(http_requests.get_last('body'))
assert payload == {'one': 1, 'str': 'abcd', 'evalme': formdata.get_display_id()}
def test_webservice_waitpoint(pub):
item = WebserviceCallStatusItem()
assert item.waitpoint
@ -1994,10 +2028,11 @@ def test_sms_with_passerelle(pub):
item.body = 'my message'
with mock.patch('wcs.wscalls.get_secret_and_orig') as mocked_secret_and_orig:
mocked_secret_and_orig.return_value = ('secret', 'localhost')
with mock.patch('qommon.misc.http_post_request') as mocked_http_post:
with mock.patch('qommon.misc._http_request') as mocked_http_post:
mocked_http_post.return_value = ('response', '200', 'data', 'headers')
item.perform(formdata)
url, payload = mocked_http_post.call_args[0]
url = mocked_http_post.call_args[0][0]
payload = mocked_http_post.call_args[1]['body']
assert 'http://passerelle.example.com' in url
assert '?nostop=1' in url
assert 'orig=localhost' in url

View File

@ -1,5 +1,4 @@
import json
import mock
import pytest
from StringIO import StringIO
@ -19,6 +18,7 @@ def pub():
pub.load_site_options()
return pub
def teardown_module(module):
clean_temporary_pub()
@ -135,3 +135,33 @@ def test_wscall_ezt(http_requests, pub):
assert template.render(variables) == '<p></p>'
template = Template('<p>[webservice.hello.foo]</p>')
assert template.render(variables) == '<p>[webservice.hello.foo]</p>'
def test_webservice_post_put_patch(http_requests, pub):
NamedWsCall.wipe()
for method in ('POST', 'PUT', 'PATCH'):
wscall = NamedWsCall()
wscall.name = 'Hello world'
wscall.request = {'method': 'PUT', 'post_data': {'toto': 'coin'},
'url': 'http://remote.example.net/json'}
try:
wscall.call()
except:
pass
assert http_requests.get_last('url') == wscall.request['url']
assert http_requests.get_last('method') == wscall.request['method']
assert json.loads(http_requests.get_last('body')) == wscall.request['post_data']
def test_webservice_delete(http_requests, pub):
NamedWsCall.wipe()
wscall = NamedWsCall()
wscall.name = 'Hello world'
wscall.request = {'method': 'DELETE', 'post_data': {'toto': 'coin'},
'url': 'http://remote.example.net/json'}
try:
wscall.call()
except:
pass
assert http_requests.get_last('url') == wscall.request['url']
assert http_requests.get_last('method') == 'DELETE'

View File

@ -127,7 +127,7 @@ class WebserviceCallStatusItem(WorkflowStatusItem):
@property
def method(self):
if self._method in ('GET', 'POST'):
if self._method in ('GET', 'POST', 'PUT', 'PATCH', 'DELETE'):
return self._method
if self.post or self.post_data:
return 'POST'
@ -174,7 +174,13 @@ class WebserviceCallStatusItem(WorkflowStatusItem):
value=self.qs_data or {},
element_value_type=ComputedExpressionWidget)
methods = collections.OrderedDict(
[('GET', _('GET')), ('POST', _('POST (JSON)'))])
[
('GET', _('GET')),
('POST', _('POST (JSON)')),
('PUT', _('PUT (JSON)')),
('PATCH', _('PATCH (JSON)')),
('DELETE', _('DELETE')),
])
if 'method' in parameters:
form.add(RadiobuttonsWidget, '%smethod' % prefix,
title=_('Method'),

View File

@ -86,7 +86,7 @@ def call_webservice(url, qs_data=None, request_signature_key=None,
payload = None
# if post_data exists, payload is a dict built from it
if method == 'POST' and post_data:
if method in ('PATCH', 'PUT', 'POST') and post_data:
payload = {}
for (key, value) in post_data.items():
try:
@ -96,20 +96,23 @@ def call_webservice(url, qs_data=None, request_signature_key=None,
# if formdata has to be sent, it's the payload. If post_data exists,
# it's added in formdata['extra']
if method == 'POST' and post_formdata:
if method in ('PATCH', 'PUT', 'POST') and post_formdata:
if formdata:
formdata_dict = formdata.get_json_export_dict()
if payload is not None:
formdata_dict['extra'] = payload
payload = formdata_dict
if method == 'POST':
if method in ('PATCH', 'PUT', 'POST'):
if payload:
headers['Content-type'] = 'application/json'
payload = json.dumps(payload, cls=JSONEncoder,
encoding=get_publisher().site_charset)
response, status, data, auth_header = qommon.misc.http_post_request(
url, payload, headers=headers)
response, status, data, auth_header = qommon.misc._http_request(
url, method=method, body=payload, headers=headers)
elif method == 'DELETE':
response, status, data, auth_header = qommon.misc._http_request(
url, method='DELETE', headers=headers)
else:
response, status, data, auth_header = qommon.misc.http_get_page(
url, headers=headers)
@ -223,7 +226,13 @@ class WsCallRequestWidget(CompositeWidget):
value=value.get('qs_data') or {},
element_value_type=ComputedExpressionWidget)
methods = collections.OrderedDict(
[('GET', _('GET')), ('POST', _('POST (JSON)'))])
[
('GET', _('GET')),
('POST', _('POST (JSON)')),
('PUT', _('PUT (JSON)')),
('PATCH', _('PATCH (JSON)')),
('DELETE', _('DELETE')),
])
self.add(RadiobuttonsWidget, 'method',
title=_('Method'),
options=methods.items(),