12

I have a FastAPI app in which routes are dynamically generated based on an DB config.

However, once the routes are defined and the app running, if the config changes, there seems to be no way to reload the config so that the routes could reflect the config. The only solution I have for now is manually restart the asgi app by restarting uvicorn.

Is there any way to fully regenerate routes without stopping the app, that could ideally be called from an URL ?

4
  • Did you find an answer to this? Commented Aug 30, 2022 at 15:08
  • 1
    @RobH Unfortunately not. The only way I managed to work around is using variable path parameters and manually check their values inside the controlers, but this removes all the benefits of FastAPI towards data checking with Pydantic model since routes are collapsed into a generic one with no type checking. Commented Sep 1, 2022 at 10:52
  • Yep. I dug through the source code and found that there's no editing of existing routes. :( Commented Sep 1, 2022 at 14:52
  • 1
    Future readers might find this answer helpful as well. Commented Mar 9, 2024 at 7:40

1 Answer 1

9

It is possible to modify routes at runtime.

FastAPI apps have the method add_api_route which allows you to dynamically define new endpoints. To remove an endpoint you will need to fiddle directly with the routes of the underlying Router.

The following code shows how to dynamically add and remove routes.

import fastapi app = fastapi.FastAPI() @app.get("/add") async def add(name: str): async def dynamic_controller(): return f"dynamic: {name}" app.add_api_route(f"/dyn/{name}", dynamic_controller, methods=["GET"]) return "ok" def route_matches(route, name): return route.path_format == f"/dyn/{name}" @app.get("/remove") async def remove(name: str): for i, r in enumerate(app.router.routes): if route_matches(r, name): del app.router.routes[i] return "ok" return "not found" 

And below is shown how to use it

$ curl 127.0.0.1:8000/dyn/test {"detail":"Not Found"} $ curl 127.0.0.1:8000/add?name=test "ok" $ curl 127.0.0.1:8000/dyn/test "dynamic: test" $ curl 127.0.0.1:8000/add?name=test2 "ok" $ curl 127.0.0.1:8000/dyn/test2 "dynamic: test2" $ curl 127.0.0.1:8000/remove?name=test "ok" $ curl 127.0.0.1:8000/dyn/test {"detail":"Not Found"} $ curl 127.0.0.1:8000/dyn/test2 "dynamic: test2" 

Note though, that if you change the routes dynamically you will need to invalidate the cache of the OpenAPI endpoint.

Sign up to request clarification or add additional context in comments.

3 Comments

That's an unexcpected answer, and it seems to fit what I was looking for. It's quite surprising that add_api_route is no documented at all ; dynamic routes seem to be such a valued feature!
How do you "invalidate the cache of the OpenAPI endpoint."? And is it possible to do dynamically add a GraphQL endpoint in a similar way (using Graphene)?
@JayjayJay To invalidate the cache and reload the new app specs: app.openapi_schema = None; app.setup()

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.