You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

FastAPI前端初始目录配置:无需修改HTML解决资源404问题

问题描述

我有一个FastAPI应用,目录结构如下:

app
.... main.py
.... client
........ index.html
........ index.js
........ style.css
........ cfg
............ index.html
............ index.js
............ style.css
........ components
............ libs
................. etc

main.py 代码:

app = FastAPI()

app.mount('/client', StaticFiles(directory='client'), name='static')

@app.get('/')
async def get():
    return FileResponse('client/index.html')

@app.get('/cfg')
async def cfg():
    return FileResponse('client/cfg/index.html')

client/index.html 核心资源引用片段:

<link href="style.css" rel="stylesheet" type="text/css">
<script src="libs/d3/d3.v7.js"></script>
<script src="./index.js" type="module" defer></script>

client/cfg/index.html 核心资源引用片段:

<script src="./index.js" type="module" defer></script>
<link href="style.css" rel="stylesheet" type="text/css">
<link href="../libs/codemirror-5.65.13/lib/codemirror.css" rel="stylesheet" type="text/css">

当前遇到的问题:

  • 访问 localhost:8000 时,HTML内的资源请求(如 /index.js)返回404,原因是请求路径未包含client前缀
  • 尝试过重定向到client/index.html,资源加载正常但URL变为localhost:8000/client/index.html,不符合需求
  • 尝试过将StaticFiles挂载到根路径,访问cfg页面时,资源会请求根目录的index.js和style.css,而非cfg文件夹下的对应文件,问题未解决
  • 无法修改HTML中的路径,需通过FastAPI配置适配
解决方案

方法一:为不同路由挂载独立的StaticFiles实例

为根路径和/cfg路径分别挂载对应目录的静态资源,确保每个页面的资源请求都能匹配到正确的文件位置:

from fastapi import FastAPI
from fastapi.staticfiles import StaticFiles
from fastapi.responses import FileResponse

app = FastAPI()

# 根路径静态资源映射到client目录
app.mount('/', StaticFiles(directory='client'), name='root_static')
# /cfg路径静态资源映射到client/cfg目录
app.mount('/cfg', StaticFiles(directory='client/cfg'), name='cfg_static')

@app.get('/')
async def get():
    return FileResponse('client/index.html')

@app.get('/cfg')
async def cfg():
    return FileResponse('client/cfg/index.html')

效果说明:

  • 访问localhost:8000时,style.css请求路径/style.css会对应client/style.css
  • 访问localhost:8000/cfg时,style.css请求路径/cfg/style.css会对应client/cfg/style.css,../libs/xxx会请求/libs/xxx,对应client/libs/xxx,完全匹配HTML中的相对路径

方法二:使用自定义中间件重写请求路径

如果不想挂载多个StaticFiles实例,可以通过中间件自动修改资源请求的路径前缀,适配不同页面的资源位置:

from fastapi import FastAPI, Request
from fastapi.staticfiles import StaticFiles
from fastapi.responses import FileResponse
from starlette.middleware.base import BaseHTTPMiddleware

app = FastAPI()

app.mount('/client', StaticFiles(directory='client'), name='static')

@app.get('/')
async def get():
    return FileResponse('client/index.html')

@app.get('/cfg')
async def cfg():
    return FileResponse('client/cfg/index.html')

class RewriteStaticMiddleware(BaseHTTPMiddleware):
    async def dispatch(self, request: Request, call_next):
        path = request.url.path
        # 处理根页面的资源请求(排除API、文档路径)
        if not path.startswith('/cfg') and not path.startswith('/docs') and not path.startswith('/openapi.json'):
            request.scope['path'] = f'/client{path}'
        # 处理cfg页面的资源请求(排除文档路径)
        elif path.startswith('/cfg/') and not path.startswith('/cfg/docs'):
            new_path = path[4:]
            request.scope['path'] = f'/client/cfg{new_path}'
        response = await call_next(request)
        return response

app.add_middleware(RewriteStaticMiddleware)

效果说明:

  • 根页面的/style.css会被重写为/client/style.css
  • cfg页面的/cfg/style.css会被重写为/client/cfg/style.css,/cfg/../libs/xxx会被解析为/client/libs/xxx,完全适配HTML中的相对路径写法

内容的提问来源于stack exchange,提问作者maltsevdm

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 23:35:38