# express-template **Repository Path**: zeng-yuhong/express-template ## Basic Information - **Project Name**: express-template - **Description**: 基于 Express 的快速模板项目,提供标准化目录结构与常用中间件配置,助力开发者高效搭建 Web 应用。 - **Primary Language**: Unknown - **License**: MulanPSL-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-09-07 - **Last Updated**: 2026-09-07 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # Express 标准中间件模板 一个开箱即用的 Express.js 项目模板,内置安全、日志、校验、鉴权、限流、统一错误处理等标准中间件链。 ## 快速开始 ```bash # 1. 安装依赖(已安装可跳过) npm install # 2. 准备环境变量 # 项目已包含可直接运行的 .env;如需从模板重建: # Windows PowerShell: Copy-Item .env.example .env # macOS/Linux: cp .env.example .env # 3. 启动 npm start # 生产/普通启动 npm run dev # 开发模式(nodemon 热重载) ``` 启动成功后访问 http://localhost:3000/api/health 应返回服务健康状态。 ## 目录结构 ``` src/ ├── app.js # 应用入口:中间件装配顺序与服务器启动 ├── config/ │ ├── cors.js # 跨域白名单配置(按 NODE_ENV 区分) │ └── rateLimit.js # 接口限流配置 ├── middleware/ │ ├── requestId.js # 请求 ID 注入(X-Request-Id 贯穿全链路) │ ├── logger.js # morgan 访问日志(含请求 ID 与耗时) │ ├── auth.js # JWT 鉴权中间件 │ ├── validation.js # Joi 参数校验中间件工厂 │ └── errorHandler.js # 全局错误处理(统一响应格式) ├── routes/ │ ├── index.js # 路由入口,挂载 /api 下所有子路由 │ ├── auth.js # 认证路由 │ └── users.js # 用户路由 ├── controllers/ │ ├── authController.js # 登录、获取当前用户 │ └── userController.js # 用户增删查 ├── services/ │ └── userService.js # 内存用户存储(demo 用,生产请替换为数据库) ├── errors/ │ ├── AppError.js # 业务错误基类 │ ├── ValidationError.js # 400 参数校验错误 │ └── NotFoundError.js # 404 资源不存在错误 └── utils/ └── response.js # 统一响应封装(success/created/noContent/fail) ``` ## 中间件装配顺序 顺序有依赖关系,调整前请阅读 `src/app.js` 中的注释: 1. `helmet` 安全响应头 2. `cors` 跨域 3. `compression` 响应压缩 4. `requestId` 请求 ID(**必须在日志之前**,否则日志拿不到 ID) 5. `logger` 访问日志 6. `cookieParser` 7. `session` 8. `body` 解析(json / urlencoded) 9. `rateLimit` 限流 10. 业务路由 `/api` 11. 404 兜底 12. `errorHandler` 全局错误处理(**必须放在最后**) ## 接口清单 | 方法 | 路径 | 鉴权 | 说明 | | --- | --- | --- | --- | | GET | `/api/health` | 否 | 健康检查 | | GET | `/api` | 否 | 接口索引 | | POST | `/api/auth/login` | 否 | 登录,返回 JWT | | GET | `/api/auth/me` | 是 | 获取当前登录用户 | | GET | `/api/users` | 否 | 用户列表 | | GET | `/api/users/:id` | 否 | 用户详情 | | POST | `/api/users` | 是 | 创建用户 | > 注:`/api/auth/me` 与 `POST /api/users` 需要请求头 `Authorization: Bearer `。 ## 演示账号 数据存于内存(`src/services/userService.js`),服务重启后重置。 | 用户名/邮箱 | 密码 | | --- | --- | | `admin` / `admin@example.com` | `admin123` | | `demo` / `demo@example.com` | `demo1234` | ## 调用示例 ```bash # 登录拿 token curl -X POST http://localhost:3000/api/auth/login \ -H "Content-Type: application/json" \ -d '{"login":"admin","password":"admin123"}' # 用 token 创建用户 curl -X POST http://localhost:3000/api/users \ -H "Content-Type: application/json" \ -H "Authorization: Bearer <上一步返回的 token>" \ -d '{"username":"alice","email":"alice@example.com","password":"password123"}' ``` ## 统一响应格式 成功: ```json { "success": true, "message": "OK", "data": {}, "requestId": "69170cd2-...", "timestamp": "2026-09-07T06:31:43.512Z" } ``` 失败: ```json { "success": false, "code": "VALIDATION_ERROR", "message": "\"login\" is not allowed to be empty; \"password\" is required", "details": [ { "field": "login", "message": "\"login\" is not allowed to be empty", "type": "string.empty" } ], "requestId": "74893753-...", "timestamp": "2026-09-07T06:33:20.541Z", "stack": "仅 NODE_ENV=development 时返回" } ``` ### 错误码对照 | HTTP | code | 触发场景 | | --- | --- | --- | | 400 | `VALIDATION_ERROR` | Joi 校验失败、用户名/邮箱重复 | | 400 | `BAD_REQUEST` | 其他客户端请求错误 | | 401 | `NO_TOKEN` | 未携带 Authorization 头 | | 401 | `INVALID_TOKEN` | token 无效或被篡改 | | 401 | `TOKEN_EXPIRED` | token 已过期 | | 404 | `RESOURCE_NOT_FOUND` | 业务资源不存在 | | 404 | `NOT_FOUND` | 路由不存在 | | 429 | `RATE_LIMIT_EXCEEDED` | 触发限流 | | 500 | `INTERNAL_SERVER_ERROR` | 未捕获的服务端异常 | ## 环境变量 | 变量 | 默认值 | 说明 | | --- | --- | --- | | `NODE_ENV` | `development` | 运行环境,影响 CORS、限流额度、堆栈返回 | | `PORT` | `3000` | 服务端口 | | `SESSION_SECRET` | — | express-session 签名密钥 | | `JWT_SECRET` | `dev-secret-change-me` | JWT 签名密钥 | | `JWT_EXPIRES_IN` | `2h` | JWT 有效期 | | `RATE_LIMIT_WINDOW_MS` | `900000` | 限流时间窗口(毫秒) | | `RATE_LIMIT_MAX` | `100` | 窗口内最大请求数(开发环境自动 ×10) | > `JWT_SECRET` 与 `SESSION_SECRET` 未配置时代码会回退到默认开发密钥以保证可运行,**生产环境必须显式设置为强随机值**。 ## 生产部署注意事项 1. **替换密钥**:`JWT_SECRET`、`SESSION_SECRET` 必须使用强随机字符串,并通过环境变量或密钥管理服务注入,不要写入代码仓库。 2. **替换数据存储**:`src/services/userService.js` 是内存实现,进程重启即丢失,需替换为真实数据库;密码当前用 sha256 存储,生产建议改用 `bcrypt`/`argon2` 加盐哈希。 3. **配置 CORS 白名单**:在 `src/config/cors.js` 的 `allowedOrigins.production` 中填入真实域名。 4. **反向代理**:若部署在 Nginx 等代理后,需设置 `app.set('trust proxy', 1)`,否则限流取到的客户端 IP 会是代理地址。 5. **Session 存储**:默认使用内存 store,多实例部署需换成 Redis 等外部存储。 6. **关闭堆栈输出**:确保 `NODE_ENV=production`,避免错误响应泄露代码路径。