Skip to content

Commit b63b457

Browse files
committed
fix rest templates
1 parent 58912bc commit b63b457

2 files changed

Lines changed: 18 additions & 2 deletions

File tree

packages/google-api-core/google/api_core/path_template.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import copy
3030
import functools
3131
import re
32+
import urllib.parse
3233

3334
# Regular expression for extracting variable parts from a path template.
3435
# The variables can be expressed as:
@@ -83,15 +84,19 @@ def _expand_variable_match(positional_vars, named_vars, match):
8384
name = match.group("name")
8485
if name is not None:
8586
try:
86-
return str(named_vars[name])
87+
val = str(named_vars[name])
88+
# Percent-encode while keeping '/' safe to preserve existing route and slash validation
89+
return urllib.parse.quote(val, safe="/")
8790
except KeyError:
8891
raise ValueError(
8992
"Named variable '{}' not specified and needed by template "
9093
"`{}` at position {}".format(name, match.string, match.start())
9194
)
9295
elif positional is not None:
9396
try:
94-
return str(positional_vars.pop(0))
97+
val = str(positional_vars.pop(0))
98+
# Percent-encode while keeping '/' safe to preserve existing route and slash validation
99+
return urllib.parse.quote(val, safe="/")
95100
except IndexError:
96101
raise ValueError(
97102
"Positional variable not specified and needed by template "

packages/google-api-core/tests/unit/test_path_template.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,17 @@
6363
{"name": "parent/child/object"},
6464
"/v1/a/parent/child/object",
6565
],
66+
# Encoding / Metacharacters in positional and named params
67+
["/v1/*", ["..?$httpMethod=DELETE#"], {}, "/v1/..%3F%24httpMethod%3DDELETE%23"],
68+
["/v1/**", ["path/../with/?and#"], {}, "/v1/path/../with/%3Fand%23"],
69+
["/v1/{name}", [], {"name": "..?$httpMethod=DELETE#"}, "/v1/..%3F%24httpMethod%3DDELETE%23"],
70+
["/v1/{name=**}", [], {"name": "path/../with/?and#"}, "/v1/path/../with/%3Fand%23"],
71+
[
72+
"/v3/{session=projects/*/locations/*/agents/*/sessions/*}:detectIntent",
73+
[],
74+
{"session": "projects/cx/locations/global/agents/a1/sessions/..?$httpMethod=DELETE#"},
75+
"/v3/projects/cx/locations/global/agents/a1/sessions/..%3F%24httpMethod%3DDELETE%23:detectIntent",
76+
],
6677
],
6778
)
6879
def test_expand_success(tmpl, args, kwargs, expected_result):

0 commit comments

Comments
 (0)