Spaces:
Running
Running
Aditya Bansal commited on
Commit ·
c0183df
1
Parent(s): 80262aa
Add OpenAPI extensions support to HTTPRoute
Browse files- Add extensions field to HTTPRoute class to store x-* fields
- Extract extensions from operation's model_extra in parser
- Add test to verify extensions are properly parsed
src/fastmcp/utilities/openapi.py
CHANGED
|
@@ -84,6 +84,7 @@ class HTTPRoute(FastMCPBaseModel):
|
|
| 84 |
schema_definitions: dict[str, JsonSchema] = Field(
|
| 85 |
default_factory=dict
|
| 86 |
) # Store component schemas
|
|
|
|
| 87 |
|
| 88 |
|
| 89 |
# Export public symbols
|
|
@@ -591,6 +592,14 @@ class OpenAPIParser(
|
|
| 591 |
getattr(operation, "responses", None)
|
| 592 |
)
|
| 593 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 594 |
route = HTTPRoute(
|
| 595 |
path=path_str,
|
| 596 |
method=method_upper, # type: ignore[arg-type] # Known valid HTTP method
|
|
@@ -602,6 +611,7 @@ class OpenAPIParser(
|
|
| 602 |
request_body=request_body_info,
|
| 603 |
responses=responses,
|
| 604 |
schema_definitions=schema_definitions,
|
|
|
|
| 605 |
)
|
| 606 |
routes.append(route)
|
| 607 |
logger.info(
|
|
|
|
| 84 |
schema_definitions: dict[str, JsonSchema] = Field(
|
| 85 |
default_factory=dict
|
| 86 |
) # Store component schemas
|
| 87 |
+
extensions: dict[str, Any] = Field(default_factory=dict)
|
| 88 |
|
| 89 |
|
| 90 |
# Export public symbols
|
|
|
|
| 592 |
getattr(operation, "responses", None)
|
| 593 |
)
|
| 594 |
|
| 595 |
+
extensions = {}
|
| 596 |
+
if hasattr(operation, "model_extra") and operation.model_extra:
|
| 597 |
+
extensions = {
|
| 598 |
+
k: v
|
| 599 |
+
for k, v in operation.model_extra.items()
|
| 600 |
+
if k.startswith("x-")
|
| 601 |
+
}
|
| 602 |
+
|
| 603 |
route = HTTPRoute(
|
| 604 |
path=path_str,
|
| 605 |
method=method_upper, # type: ignore[arg-type] # Known valid HTTP method
|
|
|
|
| 611 |
request_body=request_body_info,
|
| 612 |
responses=responses,
|
| 613 |
schema_definitions=schema_definitions,
|
| 614 |
+
extensions=extensions,
|
| 615 |
)
|
| 616 |
routes.append(route)
|
| 617 |
logger.info(
|
tests/utilities/openapi/test_openapi.py
CHANGED
|
@@ -687,6 +687,29 @@ def test_multiple_tags_preserved(bookstore_schema):
|
|
| 687 |
assert len(get_books.tags) == 3
|
| 688 |
|
| 689 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 690 |
# --- Tests for BookStore schema --- #
|
| 691 |
|
| 692 |
|
|
|
|
| 687 |
assert len(get_books.tags) == 3
|
| 688 |
|
| 689 |
|
| 690 |
+
def test_openapi_extensions(petstore_schema):
|
| 691 |
+
"""Test that OpenAPI extensions (x-*) are correctly parsed from operations."""
|
| 692 |
+
# Add extensions to a route
|
| 693 |
+
petstore_schema["paths"]["/pets"]["get"]["x-rate-limit"] = 100
|
| 694 |
+
petstore_schema["paths"]["/pets"]["get"]["x-custom-auth"] = "bearer"
|
| 695 |
+
petstore_schema["paths"]["/pets"]["get"]["x-internal"] = True
|
| 696 |
+
|
| 697 |
+
# Parse the modified schema
|
| 698 |
+
routes = parse_openapi_to_http_routes(petstore_schema)
|
| 699 |
+
|
| 700 |
+
# Find the GET /pets route
|
| 701 |
+
get_pets = next(
|
| 702 |
+
(r for r in routes if r.method == "GET" and r.path == "/pets"), None
|
| 703 |
+
)
|
| 704 |
+
assert get_pets is not None
|
| 705 |
+
|
| 706 |
+
# Should have extensions
|
| 707 |
+
assert get_pets.extensions["x-rate-limit"] == 100
|
| 708 |
+
assert get_pets.extensions["x-custom-auth"] == "bearer"
|
| 709 |
+
assert get_pets.extensions["x-internal"] is True
|
| 710 |
+
assert len(get_pets.extensions) == 3
|
| 711 |
+
|
| 712 |
+
|
| 713 |
# --- Tests for BookStore schema --- #
|
| 714 |
|
| 715 |
|