Compare commits

..

1 Commits

Author SHA1 Message Date
Serghei Mihai 09659122ea wscalls: unflatten payload when calling webservice (#66916)
gitea/wcs/pipeline/head There was a failure building this commit Details
2024-03-27 11:42:54 +01:00
2 changed files with 49 additions and 19 deletions

View File

@ -600,11 +600,11 @@ def test_webservice_with_unflattened_payload_keys(http_requests, pub):
}
pub.substitutions.feed(formdata)
item.perform(formdata)
assert http_requests.count() == 1
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 == {'foo': ['first', 'second', 'baz'], 'bar': 'example', 'form/name': 'baz'}
assert http_requests.count() == 1
http_requests.empty()
pub.loggederror_class.wipe()
@ -621,6 +621,33 @@ def test_webservice_with_unflattened_payload_keys(http_requests, pub):
== '[WSCALL] Webservice call failure because unable to unflatten payload keys (incomplete array before key "foo/1")'
)
http_requests.empty()
pub.loggederror_class.wipe()
item = WebserviceCallStatusItem()
item.url = 'http://remote.example.net'
item.record_on_errors = True
item.post_data = {'0/foo': 'value', '1/bar': 'value', 'name': '{{ form_name }}'}
item.perform(formdata)
assert (
pub.loggederror_class.select()[0].summary
== '[WSCALL] Webservice call failure because unable to unflatten payload keys (there is a mix between lists and dicts)'
)
http_requests.empty()
pub.loggederror_class.wipe()
item = WebserviceCallStatusItem()
item.url = 'http://remote.example.net'
item.record_on_errors = True
item.post_data = {'0/foo': 'value', '1/bar': 'value'}
pub.substitutions.feed(formdata)
item.perform(formdata)
assert http_requests.count() == 1
payload = json.loads(http_requests.get_last('body'))
assert payload == [{'foo': 'value'}, {'bar': 'value'}]
def test_webservice_waitpoint(pub):
item = WebserviceCallStatusItem()

View File

@ -75,21 +75,22 @@ def unflatten_keys(d):
return x.replace('//', '/')
return x
# split key by single / only
return [map_key(x) for x in re.split(r'(?<!/)/(?!/)', key)]
keys = [(split_key(key), key) for key in d]
try:
keys.sort()
except TypeError:
# sorting fail means that there is mix between lists and dicts
raise UnflattenKeysException(_('incorrect elements order'))
# sorting fail means that there is a mix between lists and dicts
raise UnflattenKeysException(_('there is a mix between lists and dicts'))
def set_path(path, orig_key, d, value, i=0):
assert path
key, tail = path[i], path[i + 1 :]
if not tail: # end of path, set thevalue
if not tail: # end of path, set the value
if isinstance(key, int):
assert isinstance(d, list)
if len(d) != key:
@ -98,24 +99,26 @@ def unflatten_keys(d):
else:
assert isinstance(d, dict)
d[key] = value
else:
new = [] if isinstance(tail[0], int) else {}
return # end of recursion
if isinstance(key, int):
assert isinstance(d, list)
if len(d) < key:
raise UnflattenKeysException(
_('incomplete array before %s in %s') % ('/'.join(map(str, path[: i + 1])), orig_key)
)
if len(d) == key:
d.append(new)
else:
new = d[key]
new = [] if isinstance(tail[0], int) else {}
if isinstance(key, int):
assert isinstance(d, list)
if len(d) < key:
raise UnflattenKeysException(
_('incomplete array before %s in %s') % ('/'.join([str(x) for x in path[: i + 1]])),
orig_key,
)
if len(d) == key:
d.append(new)
else:
new = d.setdefault(key, new)
set_path(path, orig_key, new, value, i + 1)
new = d[key]
else:
new = d.setdefault(key, new)
set_path(path, orig_key, new, value, i + 1)
# Is the first level an array or a dict ?
# Is the first level an array (ie key is like "0/param") or a dict (key is like "param/0") ?
if isinstance(keys[0][0][0], int):
new = []
else: