fix: 前端同源代理 /api → 后端(任意 IP 访问不再 NetworkError)+ SQLite 写锁等待

- 根因①:页面硬编码 http://127.0.0.1:8000/api,从 192.168.1.160:3000 访问时浏览器请求自身/跨域失败
- 根因②(500):全市场数据同步(长写事务)持有 SQLite 锁导致读接口 database is locked
- 前端:next.config.ts rewrites /api/* → http://127.0.0.1:8000/api(BACKEND_API_URL 可覆盖);
  lib/api.ts 默认相对 /api 同源(NEXT_PUBLIC_API_BASE 保留为直连覆盖项);.env.local.example 说明两种方式
- 后端:CORS 开发期 allow_origins=["*"](无凭据,上线前收紧);SQLite engine busy_timeout=30s
- USAGE FAQ 同步;验证:192.168.1.160:3000/api/health 与 /api/factors 经代理 200,CORS 头 access-control-allow-origin: *
This commit is contained in:
Simon
2026-09-06 19:00:49 +08:00
parent fc12ba89ad
commit b78852f01b
6 changed files with 53 additions and 10 deletions
+9 -2
View File
@@ -1,2 +1,9 @@
# 后端 API 基础地址(开发期)
NEXT_PUBLIC_API_BASE=http://127.0.0.1:8000/api
# 前端环境示例(复制为 .env.local 使用)
# 默认同源代理:前端 /api/* → 后端(next.config.ts rewrites,默认 http://127.0.0.1:8000)。
# 以下两种情况需要配置:
# 1) 后端跑在别的机器/端口:给 next dev/start 进程设 BACKEND_API_URL
# (注意这是 Next 服务端代理变量,不属于 NEXT_PUBLIC_*)
# BACKEND_API_URL=http://192.168.1.160:8000
# 2) 不经过 Next 代理、让浏览器直连后端:设置 NEXT_PUBLIC_API_BASE(含 /api,浏览器可访问的地址)
# NEXT_PUBLIC_API_BASE=http://192.168.1.160:8000/api
+9 -2
View File
@@ -1,5 +1,12 @@
/** 后端 API 客户端(开发期指向本地 FastAPI,地址见 .env.local)。 */
const BASE = process.env.NEXT_PUBLIC_API_BASE ?? "http://127.0.0.1:8000/api";
/**
* 后端 API 客户端。
*
* 默认走同源代理:页面请求相对路径 /api/*,由 next.config.ts 的 rewrites 转发到后端
* (默认 http://127.0.0.1:8000,可用环境变量 BACKEND_API_URL 覆盖)。
* 需要直连(不走代理)时可用 NEXT_PUBLIC_API_BASE 显式指定后端地址(含 /api)。
*/
const explicitBase = process.env.NEXT_PUBLIC_API_BASE?.replace(/\/$/, "");
const BASE = explicitBase ?? "/api";
export async function apiGet<T>(path: string): Promise<T> {
const resp = await fetch(`${BASE}${path}`);
+7
View File
@@ -2,6 +2,13 @@ import type { NextConfig } from "next";
const nextConfig: NextConfig = {
reactStrictMode: true,
// 同源代理:页面请求 /api/* → 后端 FastAPI(默认 127.0.0.1:8000)
// 使任何 IP/域名访问前端都无需 CORS 与硬编码后端地址。
// 后端地址可用环境变量 BACKEND_API_URL 覆盖(如 0.0.0.0 部署到别的机器)。
async rewrites() {
const backend = process.env.BACKEND_API_URL ?? "http://127.0.0.1:8000";
return [{ source: "/api/:path*", destination: `${backend}/api/:path*` }];
},
};
export default nextConfig;