n1kFord/notes-rest-api
GitHub: n1kFord/notes-rest-api
基于 Express.js、MongoDB 和 Redis 构建的笔记应用 REST API,涵盖 JWT 认证、CRUD、搜索分页及完整测试的生产级后端学习项目。
Stars: 0 | Forks: 0
# 📝 Notes REST API
[](https://github.com/n1kFord/notes-rest-api/actions/workflows/test.yml)
使用 Express.js、MongoDB 和 Redis 构建的笔记应用 REST API。
本项目重点关注身份验证、API 设计、数据验证、测试以及常见的后端安全实践。
## ✨ 功能
- 🔐 **JWT 身份验证** — 通过 HTTP-only Cookie 提供 Access token 和 Refresh token
- 🛡️ **CSRF 防护** — 对改变状态的请求进行 XSRF-TOKEN 验证
- 📝 **完整的 CRUD** — 创建、读取、更新和删除笔记
- 🔍 **搜索与过滤** — 全文搜索 + 基于标签的过滤
- 📄 **分页** — 针对大数据集的高效分页
- 📚 **OpenAPI/Swagger** — 交互式 API 文档
- 🚀 **生产级实践** — 速率限制、日志记录、错误处理、安全标头
- 🧪 **测试** — 使用 Jest + Supertest 的全面测试套件
## 🛠️ 技术栈
| 类别 | 技术 |
| ---------------- | ------------------------ |
| 运行时 | Node.js |
| 框架 | Express.js |
| 数据库 | MongoDB (Mongoose) |
| 缓存 | Redis |
| 容器化 | Docker, Docker Compose |
| 身份验证 | JWT, bcrypt |
| 数据验证 | express-validator |
| 文档 | Swagger UI, OpenAPI 3.0 |
| 日志 | Winston + Morgan |
| 测试 | Jest + Supertest |
| 代码检查 | ESLint + Prettier |
## 🚀 快速开始
### 前置条件
- Docker & Docker Compose(推荐)
- Node.js >= 18(用于本地开发)
### 使用 Docker(推荐)
```
# Clone repository
git clone https://github.com/n1kFord/notes-rest-api.git
cd notes-rest-api
# Start all services (MongoDB, Redis, and API)
docker compose up -d
# Check logs
docker compose logs -f
# Access API
curl http://localhost:8080/health
# Open Swagger documentation
http://localhost:8080/api/docs
# Stop services
docker compose down
# Stop and remove volumes (clears database)
docker compose down -v
```
### 本地开发
```
# Install dependencies
npm install
# Setup environment
cp .env.example .env
# Edit .env with your configuration
# Start MongoDB and Redis (using Docker)
docker compose up -d mongo redis
# Start development server
npm run dev # or npm start
# Production mode
npm start
```
### 环境变量
```
# Server
PORT=8080
NODE_ENV=development
# MongoDB
MONGODB_URI=mongodb://localhost:27017/notes_app
# Redis
REDIS_URL=redis://localhost:6379
# JWT Secrets (generate strong secrets — at least 32 chars!)
JWT_SECRET=your_super_secret_jwt_key_min_32_chars
JWT_REFRESH_SECRET=your_super_secret_refresh_key_min_32_chars
# Token Expiry (optional)
ACCESS_TOKEN_EXPIRY=15m
REFRESH_TOKEN_EXPIRY=7d
```
## 📚 API 文档
当服务器运行时,可以通过 `/api/docs` 访问交互式 Swagger UI。
### 身份验证路由 (`/api/auth`)
| 方法 | Endpoint | 描述 | 身份验证 |
| ---- | ----------- | -------------------- | -------- |
| POST | `/register` | 注册新用户 | ❌ |
| POST | `/login` | 用户登录 | ❌ |
| POST | `/refresh` | 刷新 Access token | ✅ |
| POST | `/logout` | 用户登出 | ✅ |
| GET | `/me` | 获取当前用户信息 | ✅ |
### 笔记路由 (`/api/notes`)
| 方法 | Endpoint | 描述 | 身份验证 |
| ----- | ----------------- | ---------------- | -------- |
| GET | `/` | 获取所有用户笔记 | ✅ |
| GET | `/:id` | 获取特定笔记 | ✅ |
| POST | `/` | 创建新笔记 | ✅ |
| PUT | `/:id` | 更新笔记 | ✅ |
| DELETE | `/:id` | 删除笔记 | ✅ |
| GET | `/search?q=query` | 搜索笔记 | ✅ |
| GET | `/tags/:tag` | 根据标签获取笔记 | ✅ |
## 📦 API 示例
### 注册
```
POST /api/auth/register
Content-Type: application/json
{
"email": "user@example.com",
"password": "Password123",
"confirmPassword": "Password123"
}
```
**响应:** `201 Created`
```
{ "success": true }
```
### 登录
```
POST /api/auth/login
Content-Type: application/json
{
"email": "user@example.com",
"password": "Password123"
}
```
**响应:** `200 OK`
```
{ "success": true }
```
**设置的 Cookie:**
| Cookie | 描述 |
| -------------- | --------------------------- |
| `token` | JWT Access token (HttpOnly) |
| `refreshToken` | JWT Refresh token (HttpOnly)|
| `XSRF-TOKEN` | CSRF 防护 token |
### 创建笔记
```
POST /api/notes
Cookie: token=; XSRF-TOKEN=
x-xsrf-token:
{
"title": "My First Note",
"content": "This is the content of my first note",
"tags": ["work", "important"]
}
```
**响应:** `201 Created`
```
{
"_id": "507f1f77bcf86cd799439011",
"title": "My First Note",
"content": "This is the content of my first note",
"userId": "507f1f77bcf86cd799439001",
"tags": ["work", "important"],
"createdAt": "2026-01-15T10:30:00.000Z",
"updatedAt": "2026-01-15T10:30:00.000Z"
}
```
### 获取所有笔记
```
GET /api/notes?page=1&limit=10
Cookie: token=
```
**响应:** `200 OK`
```
{
"notes": [...],
"total": 25,
"page": 1,
"totalPages": 3
}
```
### 搜索笔记
```
GET /api/notes/search?q=project&page=1&limit=10
Cookie: token=
```
## 🗄️ 数据库 Schema
### User
```
{
_id: ObjectId,
email: String (unique, indexed),
password: String (bcrypt hashed),
createdAt: Date,
updatedAt: Date
}
```
### Note
```
{
_id: ObjectId,
title: String (required, max 200),
content: String (required),
userId: ObjectId (ref: User, indexed),
tags: [String] (indexed),
createdAt: Date,
updatedAt: Date
}
```
**索引:**
- `{ userId: 1, createdAt: -1 }` — 高效分页
- `{ userId: 1, tags: 1 }` — 标签过滤
- `{ title: "text", content: "text" }` — 全文搜索
## 安全
- 使用 HTTP-only Cookie 进行 JWT 身份验证
- Refresh token 轮换
- CSRF 防护
- 请求数据验证
- 速率限制
- 使用 bcrypt 进行密码哈希处理
- 集中式错误处理
- 请求日志记录
## 🧪 测试
```
# Run all tests
npm test
# Run with coverage
npm test -- --coverage
# CI mode
npm run test:ci
```
## 📁 项目结构
```
src/
├── config/ # Database, Redis, and app configuration
├── middlewares/ # Authentication, CSRF, validation, error handling
├── models/ # MongoDB schemas
├── routers/ # API route handlers
├── store/ # Redis data storage
├── utils/ # Shared helpers and utilities
├── validations/ # Request validation rules
├── tests/ # API and integration tests
├── index.js # Application entry point
└── swagger.js # OpenAPI configuration
docker-compose.yml # Docker services configuration
Dockerfile # API container image
```
## 🚦 状态码
| 代码 | 描述 |
| ---- | --------------------- |
| 200 | OK |
| 201 | Created |
| 204 | No Content |
| 400 | Bad Request |
| 401 | Unauthorized |
| 403 | Forbidden (CSRF) |
| 404 | Not Found |
| 409 | Conflict |
| 429 | Too Many Requests |
| 500 | Internal Server Error |
## 📝 脚本
| 命令 | 描述 |
| ---------------------- | -------------------------- |
| `npm start` | 生产环境启动 |
| `npm run dev` | 使用 nodemon 进行开发 |
| `npm test` | 运行测试 |
| `npm run test:ci` | 包含覆盖率的 CI 测试 |
| `npm run lint` | ESLint 检查 |
| `npm run lint:fix` | ESLint 自动修复 |
| `npm run format` | Prettier 格式化 |
| `npm run format:check` | Prettier 检查 |
| `npm run validate` | Lint + 格式化 + 测试 |
## 📄 **许可证**
本项目基于 [MIT License](./LICENSE) 授权。
欢迎自由使用、修改和分发,但请保留原作者署名。
出于学习现代 Node.js 后端开发的目的,用 ❤️ 构建
标签:Express, GNU通用公共许可证, MITM代理, MongoDB, Node.js, Redis, REST API, Syscall, Web开发, 搜索引擎查询, 版权保护, 笔记应用, 自定义脚本, 请求拦截