mirror of
https://github.com/PrefectHQ/fastmcp.git
synced 2026-08-21 21:14:17 +02:00
Add collision detection for hyphen/underscore param name normalization
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
b3699ace91
commit
66a91a59e8
2 changed files with 30 additions and 2 deletions
|
|
@ -551,10 +551,25 @@ class FunctionResourceTemplate(ResourceTemplate):
|
|||
)
|
||||
|
||||
# Extract path and query parameters from URI template.
|
||||
# Allow hyphens in names (RFC 6570) and normalize to underscores
|
||||
# so they match Python function parameter names.
|
||||
# Allow hyphens in names and normalize to underscores so they
|
||||
# match Python function parameter names.
|
||||
raw_path_params = set(re.findall(r"{([\w-]+)(?:\*)?}", uri_template))
|
||||
raw_query_params = extract_query_params(uri_template)
|
||||
|
||||
# Detect collisions: two raw param names that normalize to the
|
||||
# same Python identifier (e.g. {user-id} and {user_id}).
|
||||
all_raw = raw_path_params | raw_query_params
|
||||
seen: dict[str, str] = {}
|
||||
for raw_name in sorted(all_raw):
|
||||
normalized = raw_name.replace("-", "_")
|
||||
if normalized in seen:
|
||||
raise ValueError(
|
||||
f"URI template parameters '{seen[normalized]}' and "
|
||||
f"'{raw_name}' both normalize to '{normalized}'. "
|
||||
f"Use one or the other, not both."
|
||||
)
|
||||
seen[normalized] = raw_name
|
||||
|
||||
path_params = {p.replace("-", "_") for p in raw_path_params}
|
||||
query_params = {p.replace("-", "_") for p in raw_query_params}
|
||||
all_uri_params = path_params | query_params
|
||||
|
|
|
|||
|
|
@ -850,6 +850,19 @@ class TestMalformedURITemplates:
|
|||
assert result is not None
|
||||
assert result["user_id"] == "alice"
|
||||
|
||||
def test_from_function_rejects_hyphen_underscore_collision(self):
|
||||
"""Two raw param names that normalize to the same key are rejected."""
|
||||
|
||||
def handler(user_id: str) -> str:
|
||||
return user_id
|
||||
|
||||
with pytest.raises(ValueError, match="both normalize to 'user_id'"):
|
||||
ResourceTemplate.from_function(
|
||||
fn=handler,
|
||||
uri_template="test://{user-id}/{user_id}",
|
||||
name="collision",
|
||||
)
|
||||
|
||||
def test_build_regex_still_works_for_valid_templates(self):
|
||||
regex = build_regex("test://{name}/{id}")
|
||||
assert regex is not None
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue