一、项目简介
这是一个用于演示环信(Easemob)回调服务的 Node.js 示例项目。项目提供了发送前(pre-send )和发送后(post-send)分离的 Webhook 接收服务,可接收环信平台发送的各种回调事件,并支持通过 Cloudflare Tunnel 将本地服务快速暴露到公网进行测试。
二、功能特点
| 特性 | 说明 |
|---|---|
| 轻量级架构 | 基于 Express 框架,快速启动和部署 |
| 分离式回调 | 发送前和发送后回调独立服务,职责清晰 |
| 公网隧道集成 | 自动使用 Cloudflare Tunnel 暴露本地服务 |
| 多格式请求支持 | 支持 JSON、原始数据、URL 编码的请求体 |
| 完整请求日志 | 记录请求头和请求体,便于调试 |
| JSON 高亮显示 | 终端输出彩色 JSON,提高可读性 |
| 可配置处理逻辑 | 支持消息内容检查、ext 字段扩展 |
| 多种启动模式 | 满足本地开发、公网测试等不同场景 |
三、技术栈
- Node.js 14+ 运行时
- Express Web 框架
- Cloudflare Tunnel(通过 cloudflared 工具)实现内网穿透
- concurrently 多进程并发管理
四、快速开始
4.1 前置条件
- Node.js 14+ 环境
- 安装
cloudflared工具(如需公网隧道功能)
4.2 安装步骤
bash
# 1. 克隆项目
git clone <项目地址>
cd easemob-callback-node-demo
# 2. 安装依赖
npm install
4.3 运行项目
bash
npm start
启动后系统会自动:
- 启动本地 Express 服务器(默认端口:3000)
- 创建 Cloudflare Tunnel 将本地服务暴露到公网
- 在控制台显示公网访问地址
五、服务端点说明
5.1 端口与服务映射
| 服务类型 | 端口 | 路径 | 说明 |
|---|---|---|---|
| 发送前回调 | 3000 | /webhook/pre-send |
消息发送前验证,决定是否放行 |
| 发送后回调 | 3001 | /webhook/post-send |
消息发送后通知,用于日志记录 |
| 健康检查(pre-send) | 3000 | / |
返回服务状态 |
| 健康检查(post-send) | 3001 | / |
返回服务状态 |
5.2 回调处理逻辑对比
| 维度 | 发送前回调(Pre-send) | 发送后回调(Post-send) |
|---|---|---|
| 触发时机 | 消息发送前 | 消息发送完成后 |
| 核心作用 | 验证并决定是否放行消息 | 记录日志、触发后续流程 |
| 返回值要求 | 必须返回 valid: true 才能放行 |
无需特殊返回值 |
| 可修改消息 | 支持扩展 ext 字段 | 不支持修改消息 |
六、获取 Webhook URL
启动项目后,控制台会显示可复制的 Webhook URL:
本地模式
发送前回调服务运行在 http://localhost:3000
完整URL: http://localhost:3000/webhook/pre-send
隧道模式(公网访问)
🌍 Webhook URL (可直接复制)
https://xxxxxx.trycloudflare.com/webhook/pre-send
💡 提示:将上述 URL 复制到环信管理后台配置为回调地址即可开始测试。
七、日志输出示例
收到回调请求时,控制台输出彩色高亮 JSON:
json
{
"callId": "easemob-demo#test2",
"timestamp": 1764932255289,
"chat_type": "groupchat",
"from": "test_user",
"to": "test_group",
"msg_id": "1234567891",
"payload": {
"bodies": [
{
"msg": "这是一条测试消息",
"type": "txt"
}
],
"ext": true,
"from": "test_user",
"to": "test_group",
"type": "groupchat"
}
}
颜色标识规则:
- 青色:键名
- 绿色:字符串值
- 黄色:数字值
- 紫色:布尔值
- 红色:null 值
八、配置说明
8.1 基础配置
在 src/pre_send_webhook.js 中可配置以下常量:
javascript
// 全局开关配置
const ALLOW_MESSAGE_SEND = true; // false 时所有消息将被阻止发送
const INSERT_TEST_EXT = true; // true 时在 ext 中插入 test 字段
8.2 启动脚本一览
| 命令 | 说明 |
|---|---|
pnpm run pre-send |
仅启动发送前回调(端口 3000) |
pnpm run post-send |
仅启动发送后回调(端口 3001) |
pnpm run both |
同时启动两个回调服务 |
pnpm run pre-send-tunnel |
启动发送前回调 + 公网隧道 |
pnpm run post-send-tunnel |
启动发送后回调 + 公网隧道 |
pnpm run start |
默认模式(兼容旧版,端口 3000) |
pnpm run tunnel |
默认模式 + 公网隧道 |
pnpm run no-tunnel |
默认模式,不创建隧道 |
8.3 自定义处理逻辑
发送前回调修改位置
src/pre_send_webhook.js 中的 /webhook/pre-send 路由
javascript
// 示例:添加自定义消息检查逻辑
app.post('/webhook/pre-send', (req, res) => {
const message = req.body.payload?.bodies?.[0]?.msg;
// 自定义:过滤敏感词
if (containsSensitiveWord(message)) {
return res.json({ valid: false });
}
// 自定义:扩展 ext 字段
if (INSERT_TEST_EXT && req.body.payload?.ext === true) {
req.body.payload.ext = { test: "added_by_webhook" };
}
return res.json({ valid: ALLOW_MESSAGE_SEND });
});
发送后回调修改位置
src/post_send_webhook.js 中的 /webhook/post-send 路由
javascript
// 示例:记录消息日志到数据库
app.post('/webhook/post-send', (req, res) => {
const { msg_id, from, to, timestamp } = req.body;
// 异步记录日志,不阻塞响应
saveMessageLog({ msg_id, from, to, timestamp });
return res.json({ success: true });
});
九、注意事项
| 类别 | 说明 |
|---|---|
| cloudflared 依赖 | 使用隧道模式前需确保已安装 cloudflared 工具 |
| 临时域名 | 隧道域名在服务重启后会变化,生产环境建议使用固定域名 |
| 生产环境 | 正式上线需配置固定域名和 HTTPS 证书 |
| 签名验证 | 生产环境务必验证环信回调签名,防止伪造请求 |
| 端口冲突 | 发送前和发送后服务使用不同端口(3000/3001),避免冲突 |
| 终端显示 | 彩色日志需要终端支持 ANSI 颜色代码 |
十、开发调试指南
10.1 本地调试
bash
# 单独启动发送前服务
node ./src/pre_send_webhook.js
# 单独启动发送后服务
node ./src/post_send_webhook.js
10.2 带隧道的调试
bash
# 启动开发模式 + 公网隧道
node ./src/scripts/boot.js pre-send --tunnel
10.3 自定义日志高亮
在 pre_send_webhook.js 或 post_send_webhook.js 中修改 highlightJson 函数,可自定义 JSON 的颜色输出规则。
十一、项目结构
easemob-callback-node-demo/
├── src/
│ ├── pre_send_webhook.js # 发送前回调服务
│ ├── post_send_webhook.js # 发送后回调服务
│ └── scripts/
│ └── boot.js # 启动脚本(含隧道逻辑)
├── package.json
└── README.md
十二、License
ISC License
本示例项目适合环信回调服务的本地开发和调试场景,结合 Cloudflare Tunnel 可快速获得公网测试地址,大大降低回调接口的联调门槛。