fastapi: Mounting StaticFiles with an APIRouter doesn't work
Describe the bug
Mounting StaticFiles with an APIRouter doesn’t work.
To Reproduce
from typing import Any
from fastapi import FastAPI, Request, APIRouter
from fastapi.staticfiles import StaticFiles
from fastapi.testclient import TestClient
router = APIRouter()
@router.get("/")
async def foo(request: Request) -> Any:
# this raises starlette.routing.NoMatchFound
return request.url_for("static", path="/bar")
app = FastAPI()
router.mount("/static", StaticFiles(directory="."), name="static")
# uncomment to fix
# app.mount("/static", StaticFiles(directory="."), name="static")
app.include_router(router)
client = TestClient(app)
client.get("/")
- Execute the script, raises NoMatchFound
- Uncomment line to mount with app instead
- Executes as expected
Expected behavior
I can use APIRouter() as if it was a FastAPI() as noted in the docs.
About this issue
- Original URL
- State: closed
- Created 4 years ago
- Reactions: 18
- Comments: 16 (3 by maintainers)
The underlying problems seems to be that the route does not get applied to the application. The cause is a very restrictive check:
https://github.com/tiangolo/fastapi/blob/f0388915a8b1cd9f3ae2259bace234ac6249c51a/fastapi/routing.py#L713-L721
This should be expanded to work with
routing.BaseRouteI have different modules with different static things in my app and wanted to separate everything. So that changing the prefix also changes the static prefix. And so they can live in another package not in the same repo.
It’s here https://fastapi.tiangolo.com/tutorial/bigger-applications/#path-operations-with-apirouter “All the same options are supported.”, but I now see that this only refers to path operations.
(btw the search in the docs is broken, it just says “Initializing search” forever)
I tried the same way as lazka and failed.
It confuses me a lot that APIRouter has
mount()which doesn’t work actually.Same here. I use @lazka’s solution for now, but it would be nice to have this more intuitive. Or at least throw an error if someone tries to mount
StaticFilesto aAPIRouter. It took some time to get to this page.any update on this? Running into the same issue.
I just ran into the same issue. I agree that at the very least there should be an error (although I would definitely support mounting within routers).
@lazka Good to know that’s a solution. Would this introduce any additional latency (because of the duplicated “bookkeeping”, FastAPI/starlette does for each ASGI request? Or is that not something to even worry about?
Basically, I’m in a similar situation where I have organized my app into around 7 different
APIRouterinstances that each have around 3 routes defined and are all imported and included in the root router. While I assumed this was one of the intended purposes ofAPIRouter, if not perhaps we should update the bigger-applications docs page or at least mention when anAPIRouterbehaves differently than theFastAPIclass.@tiangolo we probably need your opinion here on design. Would it be appropriate for
include_routerto also mount any sub-applications that have been mounted to thatAPIRouter(with appropriate prefix)? Or should we explicitly disable themountfunction onAPIRouterand make a note in the docs about it?@lazka there is an open issue about the search (#1448). It works on some platforms and not on others (not sure that’s been narrowed down yet). I have good luck on Chrome on macOS.