Juergen Eger commited on
Commit
97708fa
·
1 Parent(s): 11780c0

openapi template resources with more than 1 path parameter is not supported #267

Browse files
src/fastmcp/server/openapi.py CHANGED
@@ -286,12 +286,14 @@ class OpenAPIResource(Resource):
286
  # Find the path parameter names from the route path
287
  param_matches = re.findall(r"\{([^}]+)\}", path)
288
  if param_matches:
 
 
289
  # Number of sent parameters is number of parts -1 (assuming first part is resource identifier)
290
  expected_param_count = len(parts) -1
291
  # Map parameters from the end of the URI to the parameters in the path
292
  # Last parameter in URI (parts[-1]) maps to last parameter in path, and so on
293
  for i, param_name in enumerate(param_matches):
294
- if i < len(expected_param_count): # Ensure we don't use resource identifier as parameter
295
  param_value = parts[-1-i] # Get values from the end of parts
296
  path_params[param_name] = param_value
297
 
 
286
  # Find the path parameter names from the route path
287
  param_matches = re.findall(r"\{([^}]+)\}", path)
288
  if param_matches:
289
+ # Reverse sorting from creation order (traversal is backwards)
290
+ param_matches.sort(reverse=True)
291
  # Number of sent parameters is number of parts -1 (assuming first part is resource identifier)
292
  expected_param_count = len(parts) -1
293
  # Map parameters from the end of the URI to the parameters in the path
294
  # Last parameter in URI (parts[-1]) maps to last parameter in path, and so on
295
  for i, param_name in enumerate(param_matches):
296
+ if i < expected_param_count: # Ensure we don't use resource identifier as parameter
297
  param_value = parts[-1-i] # Get values from the end of parts
298
  path_params[param_name] = param_value
299
 
tests/server/test_openapi.py CHANGED
@@ -53,7 +53,7 @@ def fastapi_app(users_db: dict[int, User]) -> FastAPI:
53
 
54
  @app.get("/users/{user_id}/{is_active}", tags=["users", "detail"])
55
  async def get_user_active_state(user_id: int, is_active: bool) -> User | None:
56
- """Get a user by ID."""
57
  user = users_db.get(user_id)
58
  if user is not None and user.active == is_active:
59
  return user
@@ -359,7 +359,7 @@ class TestResourceTemplates:
359
  is_active = True
360
  async with Client(fastmcp_openapi_server) as client:
361
  resource_response = await client.read_resource(
362
- f"resource://openapi/get_user_users__user_type__user_id__get/{user_id}/{is_active}"
363
  )
364
  assert isinstance(resource_response[0], TextResourceContents)
365
  response_text = resource_response[0].text
 
53
 
54
  @app.get("/users/{user_id}/{is_active}", tags=["users", "detail"])
55
  async def get_user_active_state(user_id: int, is_active: bool) -> User | None:
56
+ """Get a user by ID and filter by active state."""
57
  user = users_db.get(user_id)
58
  if user is not None and user.active == is_active:
59
  return user
 
359
  is_active = True
360
  async with Client(fastmcp_openapi_server) as client:
361
  resource_response = await client.read_resource(
362
+ f"resource://openapi/get_user_active_state_users__user_id___is_active__get/{is_active}/{user_id}"
363
  )
364
  assert isinstance(resource_response[0], TextResourceContents)
365
  response_text = resource_response[0].text