fix: proxy prod api traffic through web entry

This commit is contained in:
chengkml
2026-05-16 16:56:18 +08:00
parent 7eb29346c8
commit c96bb5fa2d
5 changed files with 79 additions and 5 deletions
+1
View File
@@ -73,6 +73,7 @@
- 认证请求与 WebSocket 连接均统一复用该运行时 API 基址解析逻辑。
- `NEXT_PUBLIC_API_BASE_URL` 必须只配置“协议 + 主机 + 可选端口”,不要额外带 `/api` 前缀;当前前端请求路径已自行拼接 `/api/v1/...`,若环境变量写成 `https://host/api` 会落成 `/api/api/v1/...`
- 通过 IP:3000 直接访问站点时,后端 `API_CORS_ORIGINS` 必须显式包含该页面 origin(例如 `http://223.109.142.84:3000`);仅放行正式域名会导致浏览器在登录预检阶段返回 `Disallowed CORS origin`
- 生产若通过公网 `IP:3000` 暴露前端,而公网 `8000` 不可直达,则应由入口反代统一承接:浏览器端对 loopback API 基址一律回落到当前站点 origin,`/api/*``/api/v1/ws` 通过部署层反代到 `api:8000`,避免浏览器直接访问 `host:8000`
## 前端构建稳定性口径(2026-04-13)
+11
View File
@@ -162,6 +162,17 @@ services:
NEXT_PUBLIC_API_BASE_URL: ${NEXT_PUBLIC_API_BASE_URL}
NEXT_PUBLIC_APP_BASE_PATH: ${NEXT_PUBLIC_APP_BASE_PATH:-/fl}
NODE_ENV: production
expose:
- "3000"
restart: unless-stopped
proxy:
image: docker.m.daocloud.io/library/nginx:1.27-alpine
depends_on:
- web
- api
ports:
- "3000:3000"
volumes:
- ./nginx.conf:/etc/nginx/conf.d/default.conf:ro
restart: unless-stopped
+41
View File
@@ -0,0 +1,41 @@
server {
listen 3000;
server_name _;
client_max_body_size 200m;
location /api/v1/ws {
proxy_pass http://api:8000;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
}
location /api/ {
proxy_pass http://api:8000;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
}
location / {
proxy_pass http://web:3000;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
}
}
+25
View File
@@ -47,3 +47,28 @@
- 风险与关注点:
- 在线 `api` 仍配置 `REFRESH_COOKIE_SECURE=true`;若继续通过纯 HTTP IP 访问,刷新 token cookie 可能不会被浏览器持久化。短期内不影响本次“登录预检被拦截”的修复,但后续若要稳定保留登录态,建议切到 HTTPS 域名访问,或在明确接受风险的前提下改为 `false`
## Work Log - 认证刷新超时改为同源反代(2026-05-16)
- 背景:
- 浏览器请求 `POST http://223.109.142.84:8000/api/v1/auth/refresh` 超时,控制台报 `Failed to fetch`
- 容器内访问 `http://223.109.142.84:3000/fl` 正常返回 `200`,但访问 `http://223.109.142.84:8000/health` 仍超时;同时 `http://127.0.0.1:8000/health``api` 容器内正常返回 `200`
- 说明故障不在 `auth/refresh` 业务逻辑,而在“浏览器直连公网 `:8000`”这条访问链路。
- 本次改动:
- `web/src/lib/api.ts`
- 浏览器端在发现构建注入的 API 基址仍为 loopback 且当前页面不在 loopback 主机时,不再改写到 `当前主机:8000`,而是直接回落到 `window.location.origin`
- `deploy/pro-deploy/compose.yml`
- 生产部署新增 `proxy`nginx)服务,占用宿主机 `3000`
- `web` 改为仅在 Compose 内网暴露 `3000`,不再直接占用宿主机端口。
- `deploy/pro-deploy/nginx.conf`
- `/api/*` 反代到 `api:8000`
- `/api/v1/ws` 使用 Upgrade 头反代到 `api:8000`
- 其余页面流量反代到 `web:3000`
- 验证:
- 本地 `nft list ruleset` 显示 Docker 已为宿主机 `3000/8000` 建立映射,但容器内访问公网 `:8000` 超时、访问公网 `:3000` 正常,支持“对外入口应统一走 `3000` 反代”的判断。
- 待同步部署目录并重建 `web/proxy` 容器后,再做浏览器与 `curl` 复测。
- 风险与关注点:
- 当前在线 `REFRESH_COOKIE_SECURE=true`;若继续通过纯 HTTP IP 访问,浏览器可能仍不会持久化 refresh cookie。若部署后出现“登录后刷新即掉线”,需将当前环境的 `REFRESH_COOKIE_SECURE` 调整为 `false` 或切到 HTTPS 入口。
+1 -5
View File
@@ -31,11 +31,7 @@ export function getApiBaseUrl(): string {
return trimTrailingSlash(configured);
}
parsed.hostname = browserHost;
if (!parsed.port) {
parsed.port = "8000";
}
return trimTrailingSlash(parsed.toString());
return trimTrailingSlash(window.location.origin);
}
export const API_BASE_URL = getApiBaseUrl();