Skip to content

Commit 5fde83d

Browse files
committed
fix: Successfully added rout (BerriAI#15697)
1 parent ec7f828 commit 5fde83d

File tree

1 file changed

+109
-30
lines changed

1 file changed

+109
-30
lines changed

litellm/proxy/pass_through_endpoints/pass_through_endpoints.py

Lines changed: 109 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1593,6 +1593,79 @@ def _extract_model_from_vertex_ai_setup(setup_response: dict) -> Optional[str]:
15931593
return None
15941594

15951595

1596+
class SafeRouteAdder:
1597+
"""
1598+
Wrapper class for adding routes to FastAPI app.
1599+
Only adds routes if they don't already exist on the app.
1600+
"""
1601+
1602+
@staticmethod
1603+
def _is_path_registered(app: FastAPI, path: str, methods: List[str]) -> bool:
1604+
"""
1605+
Check if a path with any of the specified methods is already registered on the app.
1606+
1607+
Args:
1608+
app: The FastAPI application instance
1609+
path: The path to check (e.g., "/v1/chat/completions")
1610+
methods: List of HTTP methods to check (e.g., ["GET", "POST"])
1611+
1612+
Returns:
1613+
True if the path is already registered with any of the methods, False otherwise
1614+
"""
1615+
for route in app.routes:
1616+
# Use getattr to safely access route attributes
1617+
route_path = getattr(route, "path", None)
1618+
route_methods = getattr(route, "methods", None)
1619+
1620+
if route_path == path and route_methods is not None:
1621+
# Check if any of the methods overlap
1622+
if any(method in route_methods for method in methods):
1623+
return True
1624+
return False
1625+
1626+
@staticmethod
1627+
def add_api_route_if_not_exists(
1628+
app: FastAPI,
1629+
path: str,
1630+
endpoint: Any,
1631+
methods: List[str],
1632+
dependencies: Optional[List] = None,
1633+
) -> bool:
1634+
"""
1635+
Add an API route to the app only if it doesn't already exist.
1636+
1637+
Args:
1638+
app: The FastAPI application instance
1639+
path: The path for the route
1640+
endpoint: The endpoint function/callable
1641+
methods: List of HTTP methods
1642+
dependencies: Optional list of dependencies
1643+
1644+
Returns:
1645+
True if route was added, False if it already existed
1646+
"""
1647+
if SafeRouteAdder._is_path_registered(app=app, path=path, methods=methods):
1648+
verbose_proxy_logger.debug(
1649+
"Skipping route registration - path %s with methods %s already registered on app",
1650+
path,
1651+
methods,
1652+
)
1653+
return False
1654+
1655+
app.add_api_route(
1656+
path=path,
1657+
endpoint=endpoint,
1658+
methods=methods,
1659+
dependencies=dependencies,
1660+
)
1661+
verbose_proxy_logger.debug(
1662+
"Successfully added route: %s with methods %s",
1663+
path,
1664+
methods,
1665+
)
1666+
return True
1667+
1668+
15961669
class InitPassThroughEndpointHelpers:
15971670
@staticmethod
15981671
def add_exact_path_route(
@@ -1623,7 +1696,9 @@ def add_exact_path_route(
16231696
dependencies,
16241697
)
16251698

1626-
app.add_api_route(
1699+
# Use SafeRouteAdder to only add route if it doesn't exist on the app
1700+
was_added = SafeRouteAdder.add_api_route_if_not_exists(
1701+
app=app,
16271702
path=path,
16281703
endpoint=create_pass_through_route( # type: ignore
16291704
path,
@@ -1638,20 +1713,21 @@ def add_exact_path_route(
16381713
dependencies=dependencies,
16391714
)
16401715

1641-
# Register the route to prevent duplicates
1642-
_registered_pass_through_routes[route_key] = {
1643-
"endpoint_id": endpoint_id,
1644-
"path": path,
1645-
"type": "exact",
1646-
"passthrough_params": {
1647-
"target": target,
1648-
"custom_headers": custom_headers,
1649-
"forward_headers": forward_headers,
1650-
"merge_query_params": merge_query_params,
1651-
"dependencies": dependencies,
1652-
"cost_per_request": cost_per_request,
1653-
},
1654-
}
1716+
# Register the route to prevent duplicates only if it was added
1717+
if was_added:
1718+
_registered_pass_through_routes[route_key] = {
1719+
"endpoint_id": endpoint_id,
1720+
"path": path,
1721+
"type": "exact",
1722+
"passthrough_params": {
1723+
"target": target,
1724+
"custom_headers": custom_headers,
1725+
"forward_headers": forward_headers,
1726+
"merge_query_params": merge_query_params,
1727+
"dependencies": dependencies,
1728+
"cost_per_request": cost_per_request,
1729+
},
1730+
}
16551731

16561732
@staticmethod
16571733
def add_subpath_route(
@@ -1683,7 +1759,9 @@ def add_subpath_route(
16831759
dependencies,
16841760
)
16851761

1686-
app.add_api_route(
1762+
# Use SafeRouteAdder to only add route if it doesn't exist on the app
1763+
was_added = SafeRouteAdder.add_api_route_if_not_exists(
1764+
app=app,
16871765
path=wildcard_path,
16881766
endpoint=create_pass_through_route( # type: ignore
16891767
path,
@@ -1699,20 +1777,21 @@ def add_subpath_route(
16991777
dependencies=dependencies,
17001778
)
17011779

1702-
# Register the route to prevent duplicates
1703-
_registered_pass_through_routes[route_key] = {
1704-
"endpoint_id": endpoint_id,
1705-
"path": path,
1706-
"type": "subpath",
1707-
"passthrough_params": {
1708-
"target": target,
1709-
"custom_headers": custom_headers,
1710-
"forward_headers": forward_headers,
1711-
"merge_query_params": merge_query_params,
1712-
"dependencies": dependencies,
1713-
"cost_per_request": cost_per_request,
1714-
},
1715-
}
1780+
# Register the route to prevent duplicates only if it was added
1781+
if was_added:
1782+
_registered_pass_through_routes[route_key] = {
1783+
"endpoint_id": endpoint_id,
1784+
"path": path,
1785+
"type": "subpath",
1786+
"passthrough_params": {
1787+
"target": target,
1788+
"custom_headers": custom_headers,
1789+
"forward_headers": forward_headers,
1790+
"merge_query_params": merge_query_params,
1791+
"dependencies": dependencies,
1792+
"cost_per_request": cost_per_request,
1793+
},
1794+
}
17161795

17171796
@staticmethod
17181797
def remove_endpoint_routes(endpoint_id: str):

0 commit comments

Comments
 (0)