@@ -172,25 +172,31 @@ def replacer(match):
172172 return pattern , tuple (wildcard_types )
173173
174174
175- def _validate_value_against_template (
175+ def _extract_and_validate_wildcards (
176176 val : str , template_str : str | None , property_name : str | None = None
177177) -> None :
178- """Validate a variable's value against its template structure .
178+ """Extract and validate wildcard variables against path traversal rules .
179179
180- This function extracts substrings matching individual wildcards in the
181- variable's template structure and enforces safety constraints:
180+ This function attempts to structurally match the variable's value against
181+ its template. If the value structurally matches, it extracts the substrings
182+ corresponding to the individual wildcards and enforces safety constraints:
182183 - Single-segment matches ('*') must not be exactly '.' or '..' because
183184 this breaks the URI routing contract and leads to path traversal.
184185 - Multi-segment matches ('**') are checked using _validate_multi_segment_value
185186 to ensure path traversal commands do not consume the entire value or
186187 escape the starting boundaries of the matched parameter.
187188
189+ If the value does not structurally match the template, this function allows
190+ it to pass through without error. This delegates the rejection of the malformed
191+ string to the standard routing mechanisms (like `validate()`) to ensure that
192+ `additional_bindings` are evaluated correctly.
193+
188194 Examples:
189- >>> _validate_value_against_template ("us-central1", None, "region")
195+ >>> _extract_and_validate_wildcards ("us-central1", None, "region")
190196 None
191- >>> _validate_value_against_template ("..", None, "region")
197+ >>> _extract_and_validate_wildcards ("..", None, "region")
192198 ValueError("Invalid value .. for region.")
193- >>> _validate_value_against_template (
199+ >>> _extract_and_validate_wildcards (
194200 ... "projects/my-proj/locations/.", "projects/*/locations/*", "parent"
195201 ... )
196202 ValueError("Invalid value projects/my-proj/locations/. for parent.")
@@ -202,7 +208,7 @@ def _validate_value_against_template(
202208 to construct descriptive error messages.
203209
204210 Raises:
205- ValueError: If a wildcard within the value violates path traversal rules.
211+ ValueError: If a wildcard within a structurally valid value violates path traversal rules.
206212 """
207213 if template_str is None or template_str == "*" :
208214 if val in ("." , ".." ):
@@ -258,7 +264,7 @@ def _expand_variable_match(positional_vars, named_vars, match):
258264 if name is not None :
259265 try :
260266 val = str (named_vars [name ])
261- _validate_value_against_template (val , template , name )
267+ _extract_and_validate_wildcards (val , template , name )
262268 return urllib .parse .quote (val , safe = "/" )
263269 except KeyError :
264270 raise ValueError (
@@ -268,7 +274,7 @@ def _expand_variable_match(positional_vars, named_vars, match):
268274 elif positional is not None :
269275 try :
270276 val = str (positional_vars .pop (0 ))
271- _validate_value_against_template (val , positional , None )
277+ _extract_and_validate_wildcards (val , positional , None )
272278 return urllib .parse .quote (val , safe = "/" )
273279 except IndexError :
274280 raise ValueError (
0 commit comments