背景
给 fnOS 上的 OpenClaw 部署了一个 clawpanel Web 管理面板,访问 http://192.168.1.100:3080 时页面一片空白,Chrome 控制台报错:
POST http://192.168.1.100:3080/__api/health 404 (Not Found)
页面加载失败,一片白。今天记录一下完整排查和修复过程。
排查过程
Step 1:先看控制台报什么错
F12 打开开发者工具,刷新页面,看到请求 `POST /__api/health` 返回 404。
404 说明后端没有这个接口,前端收到错误后可能直接渲染白屏。
Step 2:检查端口和进程
ss -tlnp | grep 3080
# LISTEN 0 511 0.0.0.0:3080 users:(("node",pid=946337))
ps aux | grep 946337
# node server.js (在 /vol1/@apphome/.../clawpanel-web/)
端口 3080 上跑的是 node server.js,是 clawpanel-web 的静态文件服务。
Step 3:看 server.js 的路由定义
grep -n "__api" server.js
# GET /__api/openclaw/config
# PUT /__api/openclaw/config
# POST /__api/gateway/reload
# POST /__api/openclaw/config/bind-all
# GET /__api/services/status
# GET /__api/openclaw/agents
# GET /__api/openclaw/status/summary
# GET /__api/version
找遍了,没有 `/__api/health`。
所有未匹配的 `/__api/` 请求统一走到:
res.writeHead(404); res.end('{}');
这就是根本原因。
修复方案
给 server.js 加一个 `/__api/health` 端点,负责检查 OpenClaw Gateway 是否可达。
if (req.method === 'GET' && url.pathname === '/__api/health') {
const cfg = readConfig();
const gatewayHost = cfg?.gateway?.host || '127.0.0.1';
const gatewayPort = cfg?.gateway?.port || 13550;
const probe = http.request({
hostname: gatewayHost,
port: gatewayPort,
path: '/__api/health',
method: 'GET',
timeout: 3000
}, (pr) => {
let data = '';
pr.on('data', c => data += c);
pr.on('end', () => {
try {
const j = JSON.parse(data);
res.writeHead(200, {'Content-Type': 'application/json'});
res.end(JSON.stringify({ok: true, gateway: j}));
} catch {
res.writeHead(200, {'Content-Type': 'application/json'});
res.end(JSON.stringify({ok: true, gateway: {status: 'unknown'}}));
}
});
});
let responded = false;
const respond = (ok, extra) => {
if (responded) return;
responded = true;
res.writeHead(200, {'Content-Type': 'application/json'});
res.end(JSON.stringify({ok, ...extra}));
};
probe.on('error', () => respond(false, {error: 'gateway unreachable'}));
probe.on('timeout', () => { probe.destroy(); respond(false, {error: 'gateway timeout'}); });
return;
}
要点说明:
- responded 守卫:防止多个回调(error + end)同时触发导致
ERR_HTTP_HEADERS_SENT崩溃 - 同时支持 GET 和 POST:前端用的是 POST,所以两个 method 都加上
- 超时处理:3秒超时,防止 gateway 挂了时一直卡着
结果
curl -X POST http://127.0.0.1:3080/__api/health
# {"ok":false,"error":"gateway timeout"}
curl -X GET http://127.0.0.1:3080/__api/health
# {"ok":false,"error":"gateway timeout"}
返回 200 + JSON(不再是 404),页面正常加载。
gateway timeout 是因为 OpenClaw Gateway 本身没有 `/__api/health` 端点,但这不影响页面显示——前端收到 ok: false 后会做相应处理。
经验总结
- 控制台是第一信息源:404 错误直接指向”这个接口不存在”,不要猜
- 先定位进程再看代码:知道是哪个进程在跑,代码路径就清晰了
- Node.js HTTP 双写错误:error + end 同时触发是最常见坑,用守卫变量解决
- 健康检查端点:前后端分离的项目,前端往往会轮询一个 health 接口,最好一开始就约定好