Reputation: 2277
I am new to FastAPI and Python. I need to get all the routes on my root path and show it to the user. However, I could not find a way to get all the paths recursively. The API is versioned with the help of VersionedFastAPI
and the current code does not give the path inside version; it just returns generic ones.
FastAPI backend:
app = FastAPI()
router = APIRouter(
tags=["utilities"]
)
@router.get("/")
def read_root(request: Request):
url_list = [
route.path
for route in request.app.routes
]
return { "endpoints": set(url_list) }
@app.get('/foo')
@version(1)
def foo():
return "foo V1"
@app.get('/foo')
@version(2)
def foo():
return "foo V2"
app = VersionedFastAPI(app, enable_latest=True, version_format='{major}', prefix_format='/v{major}')
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"]
)
app.include_router(router)
Code for getting the path list found under \
route
url_list = [
route.path
for route in request.app.routes
]
return { "endpoints": set(url_list) }
This returns only:
["/v1/openapi.json","/v2/docs","/openapi.json","/v2/openapi.json","/v2","/","/redoc","/v1","/docs","/docs/oauth2-redirect","/v1/docs","/latest"]
However /foo
end point is missing. Any clue on this will help.
Upvotes: 3
Views: 4477
Reputation: 34600
In the example below, make sure to call get_routes()
before passing the FastAPI instance to VersionedFastAPI
. Also, there is an endpoint (i.e., /greet
) with no version specified. Thus, to make sure that such endpoints—if happen to exist in your API— will be assigned a version, you wpuld need to define a default value (might as well be the latest version) when attempting to get the version of the endpoint at this line of code: version = getattr(route.endpoint, "_api_version", (2, 0))
. By accessing the OpenAPI/Swagger UI documentation at http://127.0.0.1:8000/v1/docs and http://127.0.0.1:8000/v2/docs, you will notice that /greet
appears in both versions of the API; hence, it can be accessed by either using /v1/greet
or /v2/greet
. That is because it hadn't been given any specific version initially; however, using either endpoint, requests will be dispatched to the same path operation function.
from fastapi import FastAPI, APIRouter
from fastapi_versioning import VersionedFastAPI, version
import uvicorn
app = FastAPI()
router = APIRouter()
all_routes =[]
def get_routes():
reserved_routes = ["/openapi.json", "/docs", "/docs/oauth2-redirect", "/redoc"]
for route in app.routes:
if route.path not in reserved_routes:
if route.name is not None:
version = getattr(route.endpoint, "_api_version", (2, 0))
all_routes.append("/v" + str(version[0]) + route.path)
@router.get("/")
def index():
return { "endpoints": all_routes }
@app.get("/foo")
@version(1)
def foo():
return "foo v1"
@app.get("/foo")
@version(2)
def foo():
return "foo v2"
@app.get("/items/{item_id}")
@version(2)
def get_item(item_id: int):
return item_id
@app.get("/greet")
def greet_with_hi():
return "Hi"
get_routes()
app = VersionedFastAPI(app, version_format='{major}',prefix_format='/v{major}')
app.include_router(router)
if __name__ == '__main__':
uvicorn.run(app, host='127.0.0.1', port=8000)
Output (when accessing http://127.0.0.1:8000/):
{"endpoints":["/v1/foo","/v2/foo","/v2/items/{item_id}","/v2/greet"]}
This answer might also prove helpful, regarding retrieving the raw route path.
Upvotes: 3