DEBUG.WIKI
野草云;香港 200Mbps 峰值;不限月流量 · BGP VPS;查看套餐 →
晚安云;香港 CN2 ¥15/月
PanstarCloud:部署应用,接入 AI,云服务器与 AI 网关

FastAPI 的前端路径带点就 404,检查 SPA 回退版本

FastAPI 0.139.0 把带点的前端页面当作资源,刷新时无法进入 index.html 回退。说明 0.139.1 修复及有边界的临时路径操作。

单页应用内点击 /users/john.doe 正常,直接打开或刷新这个地址却返回 404;同一个应用里的 /users/john 又能加载。如果使用 FastAPI 0.139.0 的 app.frontend(..., fallback="index.html"),应先检查带点路径的回退判断。

0.139.0 会先看路径最后一段是否像文件扩展名,再判断请求是否需要 HTML。john.doe 和 1.2.3 因而可能被当成静态资源路径,根本没有进入 index.html 回退。前端路由还没得到页面,自然无法接管这个地址。这与末尾斜杠引发的 307 跳转是两条不同路径。

使用包含带点路径修正的版本

FastAPI 0.139.1 已正式修复这项行为:导航判断先检查 Accept 中可接受的 HTML 类型。更新兼容依赖后,保留原来的前端目录与 fallback 配置,分别检查正常页面、带点页面和缺失资源。

例如项目原本已经有打包好的 dist/index.html,对应配置仍可以是:

from fastapi import FastAPI

app = FastAPI()
app.frontend("/", directory="dist", fallback="index.html")

dist 是示例目录,应相对于服务实际工作目录存在,并包含真实构建产物。接口、认证和其他应用配置继续使用原来的设置,不要拿这几行替换整份应用。

回退针对 HTML 导航,不代表任意请求都应收到首页。检查时保留浏览器实际的 Accept;对静态资源使用原来的资源请求头。只用一个默认 Accept: */* 的客户端请求页面,可能没有覆盖浏览器导航分支。

暂时保留 0.139.0 时,只补前端拥有的路径

确实无法立刻升级时,可以为少数带点的前端入口注册普通路径操作,直接返回已有 shell。下面的片段只适用于 /users/ 由前端路由拥有的应用:

from fastapi.responses import FileResponse

@app.get("/users/{username}", include_in_schema=False)
async def spa_user(username: str):
    return FileResponse("dist/index.html")

这里的 app 是原来的 FastAPI 实例,路径操作应与原有路由一起注册。普通路径操作优先于前端处理器;因此必须确认这个前缀没有与真实用户 API 重叠。若页面外壳需要身份检查,沿用原有访问规则;include_in_schema=False 只隐藏文档,不提供鉴权。

不要为了少写几条路由添加覆盖所有地址的 /{full_path:path}。它可能连真正的 JS、CSS 或不存在的 API 都返回 HTML,随后浏览器才以 MIME 类型错误或脚本解析错误失败。这样的“所有地址都 200”会掩盖资源故障。

复核时直接打开并刷新带点页面,确认返回的是预期 HTML;另请求不存在的 .js 资源,确认它仍是 404,再检查原 API 的状态和响应类型。页面 shell 加载成功之后,还要看前端路由是否显示正确内容。升级验收完成后,撤掉临时路径前也需确认没有客户端依赖它的额外行为。