Files
photography/backend/docs/API_DOCUMENTATION.md
xujiang 0ddde92a3c feat: 完成API测试、生产环境配置和文档编写
## 🧪 API测试系统完善
- 创建完整的单元测试套件 (tests/unit_test.go)
  - 认证流程、CRUD操作、文件上传测试
  - 中间件、错误处理、性能测试
- 创建集成测试套件 (tests/integration_test.go)
  - 业务流程、数据一致性、并发测试
- 创建综合API测试 (test_api_comprehensive.http)
  - 92个测试场景,覆盖所有API端点
- 更新Makefile添加测试命令
  - test-unit, test-integration, test-api, test-cover, test-bench

## 🗄️ 生产环境数据库配置
- Docker Compose生产环境配置 (configs/docker/docker-compose.prod.yml)
  - PostgreSQL 16 + Redis 7 + Nginx + 监控栈
- 数据库初始化脚本 (configs/docker/init-db.sql)
  - 完整表结构、索引优化、触发器、视图
- 生产环境配置脚本 (scripts/production-db-setup.sh)
  - 自动化配置、连接池、备份策略、监控

## 📚 API文档完善
- 完整的API文档 (docs/API_DOCUMENTATION.md)
  - 详细接口说明、请求响应示例
  - 认证流程、错误处理、性能优化
  - SDK支持、部署指南、安全考虑
- 包含cURL示例和Postman Collection支持

## 📊 项目进度
- 总进度: 50.0% → 57.5%
- 中优先级任务: 55% → 70%
- 并行完成3个重要任务,显著提升项目完成度

## 🎯 技术成果
- 测试覆盖率大幅提升,支持自动化测试
- 生产环境就绪,支持Docker部署
- 完整的API文档,便于前后端协作
- 性能优化和监控配置,确保生产稳定性
2025-07-11 14:10:43 +08:00

853 lines
17 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Photography Portfolio API Documentation
## 📋 API 概览
Photography Portfolio API 是一个基于 go-zero 框架的 RESTful API 服务,提供完整的摄影作品集管理功能。
### 基本信息
- **API 版本**: v1.0.0
- **基础URL**: `https://api.photography.iriver.top/api/v1`
- **开发环境**: `http://localhost:8080/api/v1`
- **认证方式**: JWT Bearer Token
- **数据格式**: JSON
- **字符编码**: UTF-8
### 响应格式
所有 API 响应都遵循统一的格式:
```json
{
"code": 200,
"message": "success",
"data": {
// 实际数据
}
}
```
### 状态码
| HTTP状态码 | 业务码 | 说明 |
|-----------|-------|------|
| 200 | 200 | 请求成功 |
| 400 | 400 | 请求参数错误 |
| 401 | 401 | 未授权 |
| 403 | 403 | 权限不足 |
| 404 | 404 | 资源不存在 |
| 500 | 500 | 服务器内部错误 |
### 错误响应
```json
{
"code": 400,
"message": "参数验证失败",
"data": null
}
```
## 🔐 认证接口
### 用户注册
**接口地址**: `POST /auth/register`
**请求参数**:
```json
{
"username": "string", // 用户名3-20个字符
"email": "string", // 邮箱地址
"password": "string" // 密码6-20个字符
}
```
**响应示例**:
```json
{
"code": 200,
"message": "注册成功",
"data": {
"user": {
"id": 1,
"username": "johndoe",
"email": "john@example.com",
"avatar": "",
"status": 1,
"created_at": "2024-01-10T10:30:00Z"
},
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}
}
```
**cURL 示例**:
```bash
curl -X POST "http://localhost:8080/api/v1/auth/register" \
-H "Content-Type: application/json" \
-d '{
"username": "johndoe",
"email": "john@example.com",
"password": "password123"
}'
```
### 用户登录
**接口地址**: `POST /auth/login`
**请求参数**:
```json
{
"username": "string", // 用户名或邮箱
"password": "string" // 密码
}
```
**响应示例**:
```json
{
"code": 200,
"message": "登录成功",
"data": {
"user": {
"id": 1,
"username": "johndoe",
"email": "john@example.com",
"avatar": "/uploads/avatars/1.jpg",
"status": 1
},
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"expires_at": "2024-01-11T10:30:00Z"
}
}
```
**cURL 示例**:
```bash
curl -X POST "http://localhost:8080/api/v1/auth/login" \
-H "Content-Type: application/json" \
-d '{
"username": "johndoe",
"password": "password123"
}'
```
## 👥 用户管理接口
### 获取用户列表
**接口地址**: `GET /users`
**请求头**: `Authorization: Bearer <token>`
**查询参数**:
- `page`: 页码,默认 1
- `limit`: 每页数量,默认 10最大 100
- `status`: 用户状态,可选值 0(禁用) 1(正常)
- `keyword`: 搜索关键词
**响应示例**:
```json
{
"code": 200,
"message": "success",
"data": {
"users": [
{
"id": 1,
"username": "johndoe",
"email": "john@example.com",
"avatar": "/uploads/avatars/1.jpg",
"status": 1,
"created_at": "2024-01-10T10:30:00Z",
"updated_at": "2024-01-10T10:30:00Z"
}
],
"total": 50,
"page": 1,
"limit": 10,
"pages": 5
}
}
```
**cURL 示例**:
```bash
curl -X GET "http://localhost:8080/api/v1/users?page=1&limit=10" \
-H "Authorization: Bearer <your-token>"
```
### 获取用户详情
**接口地址**: `GET /users/{id}`
**请求头**: `Authorization: Bearer <token>`
**路径参数**:
- `id`: 用户ID
**响应示例**:
```json
{
"code": 200,
"message": "success",
"data": {
"id": 1,
"username": "johndoe",
"email": "john@example.com",
"avatar": "/uploads/avatars/1.jpg",
"status": 1,
"created_at": "2024-01-10T10:30:00Z",
"updated_at": "2024-01-10T10:30:00Z"
}
}
```
### 创建用户
**接口地址**: `POST /users`
**请求头**: `Authorization: Bearer <token>`
**请求参数**:
```json
{
"username": "string", // 用户名,必填
"email": "string", // 邮箱,必填
"password": "string", // 密码,必填
"avatar": "string", // 头像URL可选
"status": 1 // 状态可选默认1
}
```
### 更新用户
**接口地址**: `PUT /users/{id}`
**请求头**: `Authorization: Bearer <token>`
**请求参数**:
```json
{
"username": "string", // 用户名,可选
"email": "string", // 邮箱,可选
"avatar": "string", // 头像URL可选
"status": 1 // 状态,可选
}
```
### 删除用户
**接口地址**: `DELETE /users/{id}`
**请求头**: `Authorization: Bearer <token>`
**响应示例**:
```json
{
"code": 200,
"message": "用户删除成功",
"data": null
}
```
### 上传用户头像
**接口地址**: `POST /users/{id}/avatar`
**请求头**: `Authorization: Bearer <token>`
**请求格式**: `multipart/form-data`
**表单字段**:
- `file`: 图片文件(必填)
**响应示例**:
```json
{
"code": 200,
"message": "头像上传成功",
"data": {
"avatar_url": "/uploads/avatars/1_1704875400.jpg"
}
}
```
**cURL 示例**:
```bash
curl -X POST "http://localhost:8080/api/v1/users/1/avatar" \
-H "Authorization: Bearer <your-token>" \
-F "file=@avatar.jpg"
```
## 📸 照片管理接口
### 获取照片列表
**接口地址**: `GET /photos`
**查询参数**:
- `page`: 页码,默认 1
- `limit`: 每页数量,默认 10
- `category_id`: 分类ID
- `user_id`: 用户ID
- `status`: 照片状态
- `keyword`: 搜索关键词
- `sort`: 排序方式,可选值:`created_at_desc``created_at_asc``title_asc``title_desc`
**响应示例**:
```json
{
"code": 200,
"message": "success",
"data": {
"photos": [
{
"id": 1,
"title": "美丽的日落",
"description": "在海边拍摄的日落景色",
"file_path": "/uploads/photos/sunset.jpg",
"thumbnail_path": "/uploads/photos/thumbs/sunset_thumb.jpg",
"file_size": 2048576,
"mime_type": "image/jpeg",
"width": 1920,
"height": 1080,
"category_id": 1,
"category_name": "风景",
"user_id": 1,
"username": "johndoe",
"status": 1,
"view_count": 150,
"like_count": 25,
"created_at": "2024-01-10T10:30:00Z",
"updated_at": "2024-01-10T10:30:00Z"
}
],
"total": 100,
"page": 1,
"limit": 10,
"pages": 10
}
}
```
### 获取照片详情
**接口地址**: `GET /photos/{id}`
**路径参数**:
- `id`: 照片ID
**响应示例**:
```json
{
"code": 200,
"message": "success",
"data": {
"id": 1,
"title": "美丽的日落",
"description": "在海边拍摄的日落景色",
"file_path": "/uploads/photos/sunset.jpg",
"thumbnail_path": "/uploads/photos/thumbs/sunset_thumb.jpg",
"file_size": 2048576,
"mime_type": "image/jpeg",
"width": 1920,
"height": 1080,
"category": {
"id": 1,
"name": "风景",
"description": "自然风光和城市景观"
},
"user": {
"id": 1,
"username": "johndoe",
"avatar": "/uploads/avatars/1.jpg"
},
"tags": [
{
"id": 1,
"name": "精选",
"color": "#ff4444"
}
],
"status": 1,
"view_count": 150,
"like_count": 25,
"created_at": "2024-01-10T10:30:00Z",
"updated_at": "2024-01-10T10:30:00Z"
}
}
```
### 上传照片
**接口地址**: `POST /photos`
**请求头**: `Authorization: Bearer <token>`
**请求格式**: `multipart/form-data`
**表单字段**:
- `file`: 图片文件(必填)
- `title`: 照片标题(必填)
- `description`: 照片描述(可选)
- `category_id`: 分类ID可选
- `tags`: 标签ID列表逗号分隔可选
**响应示例**:
```json
{
"code": 200,
"message": "照片上传成功",
"data": {
"id": 1,
"title": "美丽的日落",
"description": "在海边拍摄的日落景色",
"file_path": "/uploads/photos/sunset_1704875400.jpg",
"thumbnail_path": "/uploads/photos/thumbs/sunset_1704875400_thumb.jpg",
"file_size": 2048576,
"mime_type": "image/jpeg",
"width": 1920,
"height": 1080,
"category_id": 1,
"user_id": 1,
"status": 1,
"created_at": "2024-01-10T10:30:00Z"
}
}
```
**cURL 示例**:
```bash
curl -X POST "http://localhost:8080/api/v1/photos" \
-H "Authorization: Bearer <your-token>" \
-F "file=@sunset.jpg" \
-F "title=美丽的日落" \
-F "description=在海边拍摄的日落景色" \
-F "category_id=1"
```
### 更新照片
**接口地址**: `PUT /photos/{id}`
**请求头**: `Authorization: Bearer <token>`
**请求参数**:
```json
{
"title": "string", // 照片标题,可选
"description": "string", // 照片描述,可选
"category_id": 1, // 分类ID可选
"status": 1 // 状态,可选
}
```
### 删除照片
**接口地址**: `DELETE /photos/{id}`
**请求头**: `Authorization: Bearer <token>`
**响应示例**:
```json
{
"code": 200,
"message": "照片删除成功",
"data": null
}
```
## 📂 分类管理接口
### 获取分类列表
**接口地址**: `GET /categories`
**查询参数**:
- `parent_id`: 父分类ID获取子分类
- `is_active`: 是否激活,可选值 0、1
- `with_count`: 是否包含照片数量统计,默认 false
**响应示例**:
```json
{
"code": 200,
"message": "success",
"data": [
{
"id": 1,
"name": "风景",
"description": "自然风光和城市景观",
"parent_id": null,
"sort_order": 1,
"is_active": 1,
"photo_count": 25,
"children": [
{
"id": 2,
"name": "海景",
"description": "海洋和海滩景色",
"parent_id": 1,
"sort_order": 1,
"is_active": 1,
"photo_count": 10
}
],
"created_at": "2024-01-10T10:30:00Z",
"updated_at": "2024-01-10T10:30:00Z"
}
]
}
```
### 获取分类详情
**接口地址**: `GET /categories/{id}`
**路径参数**:
- `id`: 分类ID
### 创建分类
**接口地址**: `POST /categories`
**请求头**: `Authorization: Bearer <token>`
**请求参数**:
```json
{
"name": "string", // 分类名称,必填
"description": "string", // 分类描述,可选
"parent_id": 1, // 父分类ID可选
"sort_order": 1, // 排序序号,可选
"is_active": 1 // 是否激活,可选
}
```
### 更新分类
**接口地址**: `PUT /categories/{id}`
**请求头**: `Authorization: Bearer <token>`
**请求参数**:
```json
{
"name": "string", // 分类名称,可选
"description": "string", // 分类描述,可选
"parent_id": 1, // 父分类ID可选
"sort_order": 1, // 排序序号,可选
"is_active": 1 // 是否激活,可选
}
```
### 删除分类
**接口地址**: `DELETE /categories/{id}`
**请求头**: `Authorization: Bearer <token>`
**响应示例**:
```json
{
"code": 200,
"message": "分类删除成功",
"data": null
}
```
## 🏷️ 标签管理接口
### 获取标签列表
**接口地址**: `GET /tags`
**查询参数**:
- `is_active`: 是否激活
- `keyword`: 搜索关键词
**响应示例**:
```json
{
"code": 200,
"message": "success",
"data": [
{
"id": 1,
"name": "精选",
"color": "#ff4444",
"description": "精选优质作品",
"is_active": 1,
"photo_count": 15,
"created_at": "2024-01-10T10:30:00Z",
"updated_at": "2024-01-10T10:30:00Z"
}
]
}
```
### 创建标签
**接口地址**: `POST /tags`
**请求头**: `Authorization: Bearer <token>`
**请求参数**:
```json
{
"name": "string", // 标签名称,必填
"color": "#ff4444", // 标签颜色,可选
"description": "string", // 标签描述,可选
"is_active": 1 // 是否激活,可选
}
```
## 🏥 健康检查接口
### 健康检查
**接口地址**: `GET /health`
**响应示例**:
```json
{
"code": 200,
"message": "success",
"data": {
"status": "ok",
"timestamp": "2024-01-10T10:30:00Z",
"version": "v1.0.0",
"uptime": "2h30m15s",
"database": "connected",
"redis": "connected"
}
}
```
## 📊 统计接口
### 获取仪表盘统计
**接口地址**: `GET /dashboard/stats`
**请求头**: `Authorization: Bearer <token>`
**响应示例**:
```json
{
"code": 200,
"message": "success",
"data": {
"users": {
"total": 150,
"active": 142,
"new_today": 5
},
"photos": {
"total": 2500,
"published": 2350,
"new_today": 25,
"total_views": 150000,
"total_likes": 8500
},
"categories": {
"total": 12,
"active": 10
},
"tags": {
"total": 25,
"active": 22
},
"storage": {
"used": "15.5GB",
"total": "100GB",
"usage_percent": 15.5
}
}
}
```
## 🔧 文件服务接口
### 静态文件访问
**接口地址**: `GET /uploads/{path}`
**路径参数**:
- `path`: 文件相对路径
**示例**:
- 照片原图: `GET /uploads/photos/sunset_1704875400.jpg`
- 缩略图: `GET /uploads/photos/thumbs/sunset_1704875400_thumb.jpg`
- 用户头像: `GET /uploads/avatars/1_1704875400.jpg`
## 📝 开发指南
### 环境配置
1. **开发环境**:
```bash
# 设置环境变量
export ENV=development
export DATABASE_HOST=localhost
export DATABASE_PORT=5432
export JWT_SECRET=your-jwt-secret
# 启动服务
go run cmd/api/main.go -f etc/photography-api.yaml
```
2. **生产环境**:
```bash
# 使用 Docker Compose
docker-compose -f configs/docker/docker-compose.prod.yml up -d
```
### 认证流程
1. 用户注册或登录获取 JWT Token
2. 在请求头中添加 `Authorization: Bearer <token>`
3. 服务器验证 Token 并提取用户信息
4. 权限检查通过后执行业务逻辑
### 错误处理
API 遵循统一的错误处理机制:
```json
{
"code": 400,
"message": "参数验证失败: 用户名不能为空",
"data": null
}
```
常见错误码:
- `401`: 未登录或 Token 无效
- `403`: 权限不足
- `400`: 参数错误
- `404`: 资源不存在
- `500`: 服务器错误
### 性能优化
1. **分页查询**: 大数据量接口支持分页,减少单次传输数据量
2. **字段过滤**: 支持 `fields` 参数指定返回字段
3. **缓存机制**: 热点数据使用 Redis 缓存
4. **数据库优化**: 合理使用索引避免N+1查询
### 安全考虑
1. **输入验证**: 所有用户输入都进行严格验证
2. **SQL注入防护**: 使用参数化查询
3. **文件上传安全**: 文件类型和大小限制
4. **Rate Limiting**: 接口频率限制
5. **CORS配置**: 跨域请求控制
## 📚 SDK 和工具
### JavaScript/TypeScript SDK
```typescript
import { PhotographyAPI } from 'photography-api-sdk';
const api = new PhotographyAPI({
baseURL: 'https://api.photography.iriver.top/api/v1',
token: 'your-jwt-token'
});
// 获取照片列表
const photos = await api.photos.list({
page: 1,
limit: 10,
category_id: 1
});
// 上传照片
const photo = await api.photos.upload({
file: fileBlob,
title: '美丽的日落',
description: '在海边拍摄的日落景色',
category_id: 1
});
```
### Postman Collection
项目提供完整的 Postman Collection包含所有接口的示例请求
```bash
# 导入 Postman Collection
curl -o photography-api.postman_collection.json \
https://raw.githubusercontent.com/photography/api-docs/main/postman/collection.json
```
### OpenAPI 规范
API 提供标准的 OpenAPI 3.0 规范文档:
- **Swagger UI**: `https://api.photography.iriver.top/swagger`
- **OpenAPI JSON**: `https://api.photography.iriver.top/api/openapi.json`
## 🚀 部署说明
### Docker 部署
```bash
# 拉取镜像
docker pull photography/api:latest
# 运行容器
docker run -d \
--name photography-api \
-p 8080:8080 \
-e DATABASE_HOST=your-db-host \
-e DATABASE_PASSWORD=your-db-password \
-e JWT_SECRET=your-jwt-secret \
photography/api:latest
```
### Kubernetes 部署
```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: photography-api
spec:
replicas: 3
selector:
matchLabels:
app: photography-api
template:
metadata:
labels:
app: photography-api
spec:
containers:
- name: api
image: photography/api:latest
ports:
- containerPort: 8080
env:
- name: DATABASE_HOST
value: "postgres-service"
- name: JWT_SECRET
valueFrom:
secretKeyRef:
name: api-secrets
key: jwt-secret
```
## 📞 支持
- **技术文档**: https://docs.photography.iriver.top
- **GitHub Issues**: https://github.com/photography/api/issues
- **邮箱支持**: api-support@photography.com
---
*最后更新: 2024-01-10*