pythonasyncioapiasyncfastapiframeworkjsonjson-schemaopenapiopenapi3pydanticpython-typespython3redocreststarletteswaggerswagger-uiuvicornweb
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
94 lines
2.9 KiB
94 lines
2.9 KiB
"""Tests for mounting StaticFiles under APIRouter (issue #10180)."""
|
|
from pathlib import Path
|
|
|
|
import pytest
|
|
from fastapi import APIRouter, FastAPI
|
|
from fastapi.staticfiles import StaticFiles
|
|
from fastapi.testclient import TestClient
|
|
|
|
|
|
def test_mount_staticfiles_under_router_with_prefix(tmp_path: Path) -> None:
|
|
"""StaticFiles mounted on APIRouter with prefix should be accessible."""
|
|
static_file = tmp_path / "hello.txt"
|
|
static_file.write_text("hello world")
|
|
|
|
app = FastAPI()
|
|
api_router = APIRouter(prefix="/api")
|
|
|
|
@api_router.get("/app")
|
|
def read_main() -> dict:
|
|
return {"message": "Hello World from main app"}
|
|
|
|
api_router.mount("/static", StaticFiles(directory=tmp_path), name="static")
|
|
app.include_router(api_router)
|
|
|
|
client = TestClient(app)
|
|
|
|
# Regular route should still work
|
|
r = client.get("/api/app")
|
|
assert r.status_code == 200
|
|
|
|
# StaticFiles should be accessible under router prefix
|
|
r = client.get("/api/static/hello.txt")
|
|
assert r.status_code == 200
|
|
assert r.text == "hello world"
|
|
|
|
|
|
def test_mount_staticfiles_under_router_without_prefix(tmp_path: Path) -> None:
|
|
"""StaticFiles mounted on APIRouter without prefix should be accessible."""
|
|
static_file = tmp_path / "test.txt"
|
|
static_file.write_text("test content")
|
|
|
|
app = FastAPI()
|
|
router = APIRouter()
|
|
router.mount("/static", StaticFiles(directory=tmp_path), name="static")
|
|
app.include_router(router)
|
|
|
|
client = TestClient(app)
|
|
|
|
r = client.get("/static/test.txt")
|
|
assert r.status_code == 200
|
|
assert r.text == "test content"
|
|
|
|
|
|
def test_mount_staticfiles_with_include_router_prefix(tmp_path: Path) -> None:
|
|
"""include_router prefix + router prefix + mount path should all combine."""
|
|
static_file = tmp_path / "file.txt"
|
|
static_file.write_text("combined prefix")
|
|
|
|
app = FastAPI()
|
|
router = APIRouter(prefix="/api")
|
|
router.mount("/static", StaticFiles(directory=tmp_path), name="static")
|
|
app.include_router(router, prefix="/v1")
|
|
|
|
client = TestClient(app)
|
|
|
|
r = client.get("/v1/api/static/file.txt")
|
|
assert r.status_code == 200
|
|
assert r.text == "combined prefix"
|
|
|
|
|
|
def test_mount_non_staticfiles_app_is_ignored() -> None:
|
|
"""Mounting a non-StaticFiles ASGI app on APIRouter should be silently ignored
|
|
(not propagated to the main app) to preserve existing behavior."""
|
|
app = FastAPI()
|
|
api_router = APIRouter(prefix="/api")
|
|
|
|
subapi = FastAPI()
|
|
|
|
@subapi.get("/sub")
|
|
def read_sub() -> dict:
|
|
return {"message": "sub"}
|
|
|
|
api_router.mount("/subapi", subapi)
|
|
app.include_router(api_router)
|
|
|
|
client = TestClient(app)
|
|
|
|
# Non-StaticFiles sub-app mount is not propagated — returns 404
|
|
r = client.get("/api/subapi/sub")
|
|
assert r.status_code == 404
|
|
|
|
# Regular routes are unaffected
|
|
# (no routes defined here, but include_router itself should not crash)
|
|
assert app is not None
|
|
|