mirror of https://github.com/tiangolo/fastapi.git
Make `APIRouter.mount` work for `StaticFiles`
This commit is contained in:
parent
d06ab3f5c7
commit
c6987ceabb
|
|
@ -1133,6 +1133,11 @@ class FastAPI(Starlette):
|
|||
scope["root_path"] = self.root_path
|
||||
await super().__call__(scope, receive, send)
|
||||
|
||||
|
||||
def mount(self, path: str, app: ASGIApp, name: str | None = None) -> None:
|
||||
self.router._mount(path, app=app, name=name)
|
||||
|
||||
|
||||
def add_api_route(
|
||||
self,
|
||||
path: str,
|
||||
|
|
|
|||
|
|
@ -74,6 +74,7 @@ from starlette.routing import (
|
|||
get_name,
|
||||
)
|
||||
from starlette.routing import Mount as Mount # noqa
|
||||
from starlette.staticfiles import StaticFiles
|
||||
from starlette.types import AppType, ASGIApp, Lifespan, Receive, Scope, Send
|
||||
from starlette.websockets import WebSocket
|
||||
from typing_extensions import deprecated
|
||||
|
|
@ -993,6 +994,20 @@ class APIRouter(routing.Router):
|
|||
self.default_response_class = default_response_class
|
||||
self.generate_unique_id_function = generate_unique_id_function
|
||||
|
||||
def mount(self, path: str, app: ASGIApp, name: str | None = None) -> None:
|
||||
"""
|
||||
Mount a StaticFiles instance.
|
||||
Will raise a FastAPIError exception if app is not an instance of StaticFiles.
|
||||
"""
|
||||
if not isinstance(app, StaticFiles):
|
||||
raise FastAPIError(
|
||||
"APIRouter does not support mounting ASGI applications other than StaticFiles."
|
||||
)
|
||||
self._mount(path=path, app=app, name=name)
|
||||
|
||||
def _mount(self, path: str, app: ASGIApp, name: str | None = None) -> None:
|
||||
super().mount(path=path, app=app, name=name)
|
||||
|
||||
def route(
|
||||
self,
|
||||
path: str,
|
||||
|
|
@ -1489,6 +1504,11 @@ class APIRouter(routing.Router):
|
|||
self.add_websocket_route(
|
||||
prefix + route.path, route.endpoint, name=route.name
|
||||
)
|
||||
elif ( # fmt: skip
|
||||
isinstance(route, routing.Mount) and isinstance(route.app, StaticFiles)
|
||||
):
|
||||
self.mount(prefix + route.path, route.app, name=route.name)
|
||||
|
||||
for handler in router.on_startup:
|
||||
self.add_event_handler("startup", handler)
|
||||
for handler in router.on_shutdown:
|
||||
|
|
|
|||
|
|
@ -0,0 +1,32 @@
|
|||
import pytest
|
||||
from fastapi import APIRouter, FastAPI
|
||||
from fastapi.exceptions import FastAPIError
|
||||
from fastapi.staticfiles import StaticFiles
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
|
||||
def test_mount_static_files_to_apirouter(tmp_path):
|
||||
static_asset = tmp_path / "index.html"
|
||||
static_asset.write_text("Hello, World!")
|
||||
|
||||
router = APIRouter()
|
||||
router.mount("/static", StaticFiles(directory=tmp_path), name="static")
|
||||
|
||||
app = FastAPI()
|
||||
app.include_router(router)
|
||||
|
||||
client = TestClient(app)
|
||||
response = client.get("/static/index.html")
|
||||
assert response.status_code == 200
|
||||
assert response.text == "Hello, World!"
|
||||
|
||||
|
||||
def test_mount_app_to_apirouter_raises():
|
||||
router = APIRouter()
|
||||
sub_app = FastAPI()
|
||||
|
||||
with pytest.raises(
|
||||
FastAPIError,
|
||||
match="APIRouter does not support mounting ASGI applications other than StaticFiles.",
|
||||
):
|
||||
router.mount("/sub", sub_app)
|
||||
Loading…
Reference in New Issue