--- belongs_to: - "[[INDEX · 铸渊·协作指令|GitHub ↔ Notion 桥接协议]]" --- # 🔧 铸渊+舒舒指令|修复 Pipeline C 飞书广播推送 · 新增 /push-broadcast 路由(2026-03-15·霜砚签发) --- ## 一、错误日志(原文) ``` 📢 推送广播到飞书... 标题: BC-M23-003-AW 目标: ou_3bd223b67374fd102edd4223244a7542 HTTP 响应: 405 405 Not Allowed

405 Not Allowed


nginx/1.24.0
❌ 推送失败 (HTTP 405) ``` --- ## 二、问题分析 Pipeline C 的 `push-broadcast-feishu.sh`(或类似脚本)向服务器发送 POST 请求推送广播,但: 1. **nginx** 没有配置该路由的 proxy_pass,直接返回 405 2. **舒舒(gateway-server.js)** 没有 `/push-broadcast` 路由来接收和处理广播推送 3. 即使有路由,还需要舒舒调用**飞书发消息 API** 把广播内容发给目标用户 --- ## 三、修复指令 ### 3.1 舒舒:新增 /push-broadcast POST 路由 **文件位置**:`feishu-bot/index.js`(或 `gateway-server.js`,取决于实际结构) ```jsx // ============ 广播推送路由 ============ // Pipeline C 调用此路由,将广播推送到飞书 app.post('/push-broadcast', async (req, res) => { try { // 1. 验证 token const token = req.headers['x-push-token'] || req.body.token; if (token !== process.env.PUSH_BROADCAST_TOKEN) { return res.status(401).json({ error: 'Invalid token' }); } // 2. 解析请求体 const { title, content, target_open_id, chat_id } = req.body; if (!content) { return res.status(400).json({ error: 'Missing content' }); } // 3. 获取飞书 tenant_access_token const tokenRes = await fetch('https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ app_id: process.env.FEISHU_APP_ID, app_secret: process.env.FEISHU_APP_SECRET }) }); const tokenData = await tokenRes.json(); const accessToken = tokenData.tenant_access_token; // 4. 发送飞书消息 // 优先发到群聊(chat_id),否则发给个人(target_open_id) const receive_id_type = chat_id ? 'chat_id' : 'open_id'; const receive_id = chat_id || target_open_id; const msgRes = await fetch(`https://open.feishu.cn/open-apis/im/v1/messages?receive_id_type=${receive_id_type}`, { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${accessToken}` }, body: JSON.stringify({ receive_id: receive_id, msg_type: 'text', content: JSON.stringify({ text: `📡 新广播 ${title || ''}\n\n${content}` }) }) }); const msgData = await msgRes.json(); if (msgData.code === 0) { console.log(`✅ 广播推送成功: ${title} → ${receive_id}`); res.json({ success: true, message_id: msgData.data?.message_id }); } else { console.error(`❌ 飞书发送失败:`, msgData); res.status(500).json({ error: msgData.msg, code: msgData.code }); } } catch (err) { console.error('❌ push-broadcast error:', err.message); res.status(500).json({ error: err.message }); } }); ``` ### 3.2 nginx:添加 proxy_pass(如果 /push-broadcast 没有被代理) **文件位置**:`/etc/nginx/conf.d/guanghulab.conf`(或对应的 nginx 配置文件) 在 server block 中确认有如下配置: ``` location /push-broadcast { proxy_pass http://127.0.0.1:3080; # 舒舒端口,按实际修改 proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header Content-Type $content_type; } ``` 如果舒舒已经有一个通配 location 代理所有 API 请求(如 `location /api/`),则需要确认 `/push-broadcast` 路径在代理范围内,或者单独加一条。 ### 3.3 Pipeline C 脚本:确认请求格式 Pipeline C 的推送脚本应该发送如下格式的 POST 请求: ```bash curl -X POST https://guanghulab.com/push-broadcast \ -H "Content-Type: application/json" \ -H "X-Push-Token: ${PUSH_BROADCAST_TOKEN}" \ -d '{ "title": "BC-M23-003-AW", "content": "广播正文内容...", "target_open_id": "ou_3bd223b67374fd102edd4223244a7542", "chat_id": "(可选,群聊 ID)" }' ``` --- ## 四、环境变量确认 舒舒服务器上需要以下环境变量(`.env` 文件或 PM2 ecosystem): | **变量名** | **用途** | **来源** | | --- | --- | --- | | `FEISHU_APP_ID` | 飞书应用 App ID | 飞书开放平台 → 应用凭证 | | `FEISHU_APP_SECRET` | 飞书应用 App Secret | 飞书开放平台 → 应用凭证 | | `PUSH_BROADCAST_TOKEN` | 推送鉴权 token | 与 GitHub Secret 中的 PUSH_BROADCAST_TOKEN 一致:`guanghu-push-2026` | **注意**:`FEISHU_APP_ID` 和 `FEISHU_APP_SECRET` 舒舒发消息时就应该已经有了(舒舒接收飞书回调时用的同一个应用)。确认这两个变量在 `.env` 里存在即可。 --- ## 五、验收标准 - [ ] 服务器上 `curl -X POST https://guanghulab.com/push-broadcast` 不再返回 405 - [ ] 带正确 token 和 content 的 POST 请求返回 `{"success": true}` - [ ] 飞书端收到广播消息 - [ ] 完整链路测试:飞书发 SYSLOG → Pipeline A/B/C 全绿 → 飞书收到新广播 --- ## 六、执行确认 铸渊完成后,在本页下方追加一行: ``` ✅ push-broadcast 路由已部署 · [日期时间] · commit SHA ```