背景
本次联调场景:
- 后端机器:
192.168.2.237:5001 - 前端同事机器:
192.168.2.218:3000 - 前端 dev-proxy 预期地址:
192.168.2.218:5001 - 出问题接口:
/console/api/account/profile
前端最初访问:
text
http://192.168.2.218:5001/console/api/account/profile
一直失败。
最后确认:不是后端接口代码问题,而是联调环境里依次踩到了三个问题:
192.168.2.218:5001没有进程监听。- dev-proxy 启动后 CORS 允许来源不对。
- 登录成功后
profile401,本质是 cookie 登录态没有正确落到同一个访问链路。
最终结论
前端页面、API 代理、后端服务的关系要清楚:
text
浏览器
-> http://192.168.2.218:3000 前端页面
-> http://192.168.2.218:5001/console/api 前端 dev-proxy
-> http://192.168.2.237:5001/console/api 后端 Flask API
如果前端配置让浏览器请求 192.168.2.218:5001,那么 2.218 机器上必须真的启动 dev-proxy 并监听 5001。
如果不想跑 dev-proxy,就让前端直接请求后端:
text
http://192.168.2.237:5001/console/api
不要让浏览器请求一个没人监听的地址。
问题一:192.168.2.218:5001 根本没服务
现象
从后端机器访问:
powershell
Test-NetConnection 192.168.2.218 -Port 5001
结果:
text
TcpTestSucceeded: False
接口请求:
powershell
Invoke-WebRequest http://192.168.2.218:5001/console/api/account/profile
报:
text
无法连接到远程服务器
根因
前端同事机器执行:
powershell
netstat -ano | findstr :5001
返回空,说明 2.218:5001 没有任何进程监听。
而后端机器执行:
text
TCP 0.0.0.0:5001 LISTENING
说明真正监听 5001 的是后端机器 192.168.2.237,不是前端机器 192.168.2.218。
解决
前端同事需要启动 dev-proxy:
bash
pnpm -C web run dev:proxy
并确保 web/.env.local 里是:
env
DEV_PROXY_HOST=0.0.0.0
DEV_PROXY_PORT=5001
DEV_PROXY_TARGET=http://192.168.2.237:5001
DEV_PROXY_PUBLIC_TARGET=http://192.168.2.237:5001
再次执行:
powershell
netstat -ano | findstr :5001
应该看到:
text
0.0.0.0:5001 LISTENING
如果是:
text
127.0.0.1:5001 LISTENING
说明只能本机访问,局域网其他机器访问不了。
问题二:DEV_PROXY_HOST=127.0.0.1 只能本机访问
含义
env
DEV_PROXY_HOST=127.0.0.1
表示 dev-proxy 只监听本机回环地址。
也就是说只有前端同事自己机器能访问:
text
http://127.0.0.1:5001
其他机器访问:
text
http://192.168.2.218:5001
会失败。
正确配置
env
DEV_PROXY_HOST=0.0.0.0
含义是监听所有网卡,包括局域网 IP:
text
192.168.2.218:5001
问题三:system-features 200,但浏览器 CORS 报错
现象
接口:
text
http://192.168.2.218:5001/console/api/system-features
命令行请求返回 200,但浏览器仍报错。
浏览器里看到:
text
Referrer Policy: strict-origin-when-cross-origin
这行本身不是错误,只是浏览器默认策略提示。
真正的问题是 CORS。
排查结果
直接请求后端:
text
http://192.168.2.237:5001/console/api/system-features
Origin: http://192.168.2.218:3000
后端返回:
text
Access-Control-Allow-Origin: http://192.168.2.218:3000
说明后端 CORS 是对的。
但经过 dev-proxy:
text
http://192.168.2.218:5001/console/api/system-features
Origin: http://192.168.2.218:3000
返回变成:
text
Access-Control-Allow-Origin: http://192.168.2.237:5001
这和浏览器页面来源不一致:
text
http://192.168.2.218:3000
浏览器会拦截。
解决
前端同事需要在 web/dev-proxy.config.ts 里加:
ts
cors: {
allowedOrigins: [
'http://192.168.2.218:3000',
],
},
注意:
env
NEXT_ALLOWED_DEV_ORIGINS=192.168.2.218
管的是 Next dev server,不管 @langgenius/dev-proxy 的 CORS。
问题四:登录接口 200,但 /account/profile 401
现象
后端日志:
text
POST /console/api/login 200
GET /console/api/account/profile 401
POST /console/api/refresh-token 401
含义
登录接口成功了,但后续请求没有带上有效的:
access_tokenrefresh_token
所以 /account/profile 报 401。
常见原因
前端页面和 API 不是同一个 host。
比如:
text
前端页面:http://192.168.2.218:3000
后端 API:http://192.168.2.237:5001
Dify 默认:
env
COOKIE_DOMAIN=
表示 cookie 绑定当前响应 host。
如果登录请求和 profile 请求不在同一个稳定链路下,浏览器可能不会把登录 cookie 带到后续请求里。
推荐解决
让浏览器统一请求前端同事机器上的 dev-proxy:
text
前端页面:http://192.168.2.218:3000
API 请求:http://192.168.2.218:5001/console/api
dev-proxy 转发到:http://192.168.2.237:5001/console/api
这样浏览器看到的是统一的 192.168.2.218,cookie 更容易正常工作。
前端需要做的事情
1. web/.env.local
推荐配置:
env
CONSOLE_API_URL=http://192.168.2.237:5001
NEXT_PUBLIC_API_PREFIX=http://192.168.2.218:5001/console/api
NEXT_PUBLIC_PUBLIC_API_PREFIX=http://192.168.2.218:5001/api
NEXT_PUBLIC_SOCKET_URL=ws://192.168.2.218:5001
DEV_PROXY_TARGET=http://192.168.2.237:5001
DEV_PROXY_PUBLIC_TARGET=http://192.168.2.237:5001
DEV_PROXY_HOST=0.0.0.0
DEV_PROXY_PORT=5001
2. web/dev-proxy.config.ts
需要允许前端页面来源:
ts
export default {
server: {
host: DEV_PROXY_HOST,
port: DEV_PROXY_PORT,
},
cors: {
allowedOrigins: [
'http://192.168.2.218:3000',
],
},
routes: [
// 原 routes 保持不变
],
} satisfies DevProxyConfig
3. 重启服务
修改 env 或 proxy config 后,需要重启:
bash
pnpm -C web run dev:proxy
pnpm -C web run dev
4. 检查端口
在前端机器执行:
powershell
netstat -ano | findstr :5001
正确结果应该包含:
text
0.0.0.0:5001 LISTENING
后端需要做的事情
1. Flask 必须监听局域网地址
后端启动需要类似:
bash
flask run --host 0.0.0.0 --port 5001 --debug
日志里看到:
text
Running on all addresses (0.0.0.0)
说明不是只监听 127.0.0.1。
2. 后端 .env 推荐配置
本次联调推荐:
env
CONSOLE_API_URL=http://192.168.2.218:5001
CONSOLE_WEB_URL=http://192.168.2.218:3000
APP_WEB_URL=http://192.168.2.218:3000
CONSOLE_CORS_ALLOW_ORIGINS=http://192.168.2.218:3000,*
WEB_API_CORS_ALLOW_ORIGINS=http://192.168.2.218:3000,*
COOKIE_DOMAIN=
说明:
CONSOLE_WEB_URL:后端认为 Console 前端页面在哪里。CONSOLE_API_URL:后端对外暴露的 Console API 地址。使用 dev-proxy 时,可以写前端同事的代理地址。CONSOLE_CORS_ALLOW_ORIGINS:允许访问 Console API 的前端来源。COOKIE_DOMAIN=:保持空,使用当前 host 绑定 cookie。
3. 后端接口状态判断
未登录直接请求:
powershell
Invoke-WebRequest http://192.168.2.237:5001/console/api/account/profile
返回 401 是正常的。
因为接口有登录要求:
text
/console/api/account/profile
-> setup_required
-> login_required
-> account_initialization_required
只要不是"无法连接远程服务器",就说明网络链路已经通了。
常用排查命令
检查端口是否通
powershell
Test-NetConnection 192.168.2.218 -Port 5001
结果含义:
text
TcpTestSucceeded: False
表示端口不通,优先查监听、防火墙、进程是否启动。
text
TcpTestSucceeded: True
表示网络层通了,再看 HTTP 状态码、CORS、cookie。
检查本机监听
powershell
netstat -ano | findstr :5001
结果含义:
text
0.0.0.0:5001 LISTENING
局域网可访问。
text
127.0.0.1:5001 LISTENING
只有本机可访问。
空结果表示没有服务监听 5001。
检查接口
powershell
Invoke-WebRequest http://192.168.2.218:5001/console/api/system-features
200 表示基础接口通。
powershell
Invoke-WebRequest http://192.168.2.218:5001/console/api/account/profile
未登录返回 401 是正常的。
配置项速查
| 配置项 | 属于 | 作用 |
|---|---|---|
NEXT_PUBLIC_API_PREFIX |
前端 | 浏览器访问 Console API 的前缀 |
NEXT_PUBLIC_PUBLIC_API_PREFIX |
前端 | 浏览器访问 WebApp 公开 API 的前缀 |
NEXT_PUBLIC_SOCKET_URL |
前端 | WebSocket 地址 |
CONSOLE_API_URL |
前端/后端 | 服务端侧 Console API origin,或后端对外 API 地址 |
DEV_PROXY_TARGET |
前端 dev-proxy | 代理最终转发到哪个后端 |
DEV_PROXY_PUBLIC_TARGET |
前端 dev-proxy | 公开 API 代理目标 |
DEV_PROXY_HOST |
前端 dev-proxy | dev-proxy 监听地址,局域网联调用 0.0.0.0 |
DEV_PROXY_PORT |
前端 dev-proxy | dev-proxy 监听端口 |
CONSOLE_WEB_URL |
后端 | 后端认为 Console Web 页面地址是什么 |
CONSOLE_CORS_ALLOW_ORIGINS |
后端 | 允许哪些来源访问 Console API |
WEB_API_CORS_ALLOW_ORIGINS |
后端 | 允许哪些来源访问 WebApp API |
COOKIE_DOMAIN |
后端 | cookie 域名,空值表示绑定当前 host |
最终经验
这类问题不要一上来改接口代码。
按顺序排:
- 端口是否监听。
- 局域网是否能连。
- dev-proxy 是否启动。
- CORS 头是否等于页面 origin。
- 登录 cookie 是否被后续请求带上。
- 最后才看后端接口逻辑。
本次最终能登录,说明:
- 后端
/console/api/account/profile接口没问题。 - 后端 CORS 配置没问题。
- 主要问题在前端 dev-proxy 的启动、监听地址和 CORS 允许来源。