Skip to content

Commit b60a88f

Browse files
committed
fix: Improve transcodding error message
This fixes googleapis#441 and googleapis#440. Also, with this change we stop outputting the whole request message in transcodding erro message to prevent leaking any confidential information from a request message in a form of an error in a log message.
1 parent fe617c2 commit b60a88f

File tree

2 files changed

+25
-8
lines changed

2 files changed

+25
-8
lines changed

google/api_core/path_template.py

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -272,23 +272,26 @@ def transcode(http_options, message=None, **request_kwargs):
272272
ValueError: If the request does not match the given template.
273273
"""
274274
transcoded_value = message or request_kwargs
275+
bindings = []
275276
for http_option in http_options:
276277
request = {}
277278

278279
# Assign path
279280
uri_template = http_option["uri"]
280-
path_fields = [
281-
match.group("name") for match in _VARIABLE_RE.finditer(uri_template)
281+
fields = [
282+
(m.group("name"), m.group("template")) for m in _VARIABLE_RE.finditer(uri_template)
282283
]
283-
path_args = {field: get_field(transcoded_value, field) for field in path_fields}
284+
bindings.append((uri_template, fields))
285+
286+
path_args = {field: get_field(transcoded_value, field) for field, _ in fields}
284287
request["uri"] = expand(uri_template, **path_args)
285288

286289
if not validate(uri_template, request["uri"]) or not all(path_args.values()):
287290
continue
288291

289292
# Remove fields used in uri path from request
290293
leftovers = copy.deepcopy(transcoded_value)
291-
for path_field in path_fields:
294+
for path_field, _ in fields:
292295
delete_field(leftovers, path_field)
293296

294297
# Assign body and query params
@@ -316,8 +319,21 @@ def transcode(http_options, message=None, **request_kwargs):
316319
request["method"] = http_option["method"]
317320
return request
318321

319-
raise ValueError(
320-
"Request {} does not match any URL path template in available HttpRule's {}".format(
321-
request_kwargs, [opt["uri"] for opt in http_options]
322+
bindings_description = [
323+
"\n\tURI: \"{}\""
324+
"\n\tRequired request fields:\n\t\t{}".format(
325+
uri,
326+
"\n\t\t".join(["field: \"{}\", pattern: \"{}\"".format(n, p if p else "*") for n, p in fields])
322327
)
328+
for uri, fields in bindings
329+
]
330+
331+
raise ValueError(
332+
"Invalid request."
333+
"\nSome of the fields of the request message are either not initialized or "
334+
"initialized with an invalid value."
335+
"\nPlease make sure your request matches at least one accepted HTTP binding."
336+
"\nTo match a binding the request message must have all the required fields "
337+
"initialized with values matching their patterns as "
338+
"listed below:{}".format("\n".join(bindings_description))
323339
)

tests/unit/test_path_template.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -629,8 +629,9 @@ def test_transcode_with_additional_bindings(
629629
)
630630
def test_transcode_fails(http_options, message, request_kwargs):
631631
http_options, _ = helper_test_transcode(http_options, range(4))
632-
with pytest.raises(ValueError):
632+
with pytest.raises(ValueError) as exc_info:
633633
path_template.transcode(http_options, message, **request_kwargs)
634+
assert str(exc_info.value).count("URI") == len(http_options)
634635

635636

636637
def helper_test_transcode(http_options_list, expected_result_list):

0 commit comments

Comments
 (0)