在使用 FastAPI 和 Vue3 进行前后端分离开发时,CORS(跨域资源共享)是一个常见的问题。通常情况下,通过配置 CORSMiddleware 即可解决。
但最近在 Windows 环境下开发时,我遇到了一个极其隐蔽的情况,浏览器持续报 CORS 错误,即使后端配置完全正确也无法修复。排查后发现,根本原因并非代码问题,而是开发工具在重启时残留了僵尸进程。
本文记录了该问题的排查过程和解决方法。
开发环境:
-
后端:FastAPI (Python)
-
前端:Vue3 + Vite
-
系统:Windows
起初问题表现得非常标准。前端试图访问后端接口时,浏览器控制台抛出了 Access-Control-Allow-Origin 头缺失的错误,并随后提示 Network Error。按照常规思路,我首先检查了 FastAPI 的 CORSMiddleware 配置,确认 allow_origins 包含了前端的开发地址。为了排除配置过严的可能性,我甚至尝试暂时允许所有来源,但问题依然没有解决。接着考虑到 FastAPI 对 URL 末尾斜杠的敏感性,我仔细核对了前后端的路由定义,排除了因 307 重定向导致的预检请求失败。我也尝试了更换 localhost 为 127.0.0.1,甚至修改了 Uvicorn 的监听地址,但所有的尝试都未能消除那个红色的报错。
在反复修改代码并重启服务的过程中,我注意到一个极易被忽视的反常细节,尽管浏览器一直在报错,但运行后端的终端窗口内却没有任何日志输出。正常情况下,无论是请求被拒还是内部报错,服务端都应该会有相应的记录。终端的静默意味着请求根本没有到达我当前看到的这个 FastAPI 进程。这让我意识到,问题可能出在网络连接或进程本身,而不是代码逻辑。
我打开 Windows 任务管理器发现后台竟然同时运行着多个 python.exe 进程。在 Windows 终端下运行带有热重载(--reload)功能的 Uvicorn 服务时,启动的不仅是主进程,还有负责监听的子进程。当我使用 Ctrl+C 停止服务时,有时系统只终止了父进程,而实际占用端口的子进程未能正常退出,变成了所谓的"僵尸进程"。
这意味着,虽然在编辑器终端里看似重启了服务,但实际上 8000 端口依然被上一次、甚至很久之前的旧进程死死占用。浏览器发出的请求实际上是被这个运行着旧代码(可能是 CORS 配置尚未生效的版本)的僵尸进程接收并拒绝了。这也是为什么当前的新终端里看不到任何访问日志的原因。
解决这个问题的方法非常简单,只需要彻底清理环境。在终端执行 taskkill /F /IM python.exe 命令或者直接在任务管理器强制结束所有 Python 进程,然后重新启动服务。再次刷新前端页面后就恢复正常。