Files
photography/backend/test_api_comprehensive.http
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

723 lines
17 KiB
HTTP

### Photography Portfolio API
###
@baseUrl = http://localhost:8080/api/v1
@token =
### ===============================================
###
### ===============================================
### 1. -
GET {{baseUrl}}/health
Content-Type: application/json
### ===============================================
###
### ===============================================
### 2. -
POST {{baseUrl}}/auth/register
Content-Type: application/json
{
"username": "testuser_{{$timestamp}}",
"email": "test{{$timestamp}}@example.com",
"password": "testpass123"
}
### 3. -
POST {{baseUrl}}/auth/register
Content-Type: application/json
{
"username": "admin",
"email": "admin2@example.com",
"password": "testpass123"
}
### 4. -
POST {{baseUrl}}/auth/register
Content-Type: application/json
{
"username": "testuser2",
"email": "invalid-email",
"password": "testpass123"
}
### 5. -
POST {{baseUrl}}/auth/register
Content-Type: application/json
{
"username": "testuser3",
"email": "test3@example.com",
"password": "123"
}
### 6. -
POST {{baseUrl}}/auth/login
Content-Type: application/json
{
"username": "admin",
"password": "admin123"
}
### 7. - 使
POST {{baseUrl}}/auth/login
Content-Type: application/json
{
"username": "admin@photography.com",
"password": "admin123"
}
### 8. -
POST {{baseUrl}}/auth/login
Content-Type: application/json
{
"username": "admin",
"password": "wrongpassword"
}
### 9. -
POST {{baseUrl}}/auth/login
Content-Type: application/json
{
"username": "nonexistent",
"password": "password123"
}
### ===============================================
### ()
### ===============================================
### 10. -
GET {{baseUrl}}/users
Content-Type: application/json
### 11. -
GET {{baseUrl}}/users
Content-Type: application/json
Authorization: Bearer {{token}}
### 12. -
GET {{baseUrl}}/users?page=1&limit=5&status=1
Content-Type: application/json
Authorization: Bearer {{token}}
### 13. -
GET {{baseUrl}}/users?keyword=admin
Content-Type: application/json
Authorization: Bearer {{token}}
### 14. -
GET {{baseUrl}}/users/1
Content-Type: application/json
Authorization: Bearer {{token}}
### 15. -
GET {{baseUrl}}/users/99999
Content-Type: application/json
Authorization: Bearer {{token}}
### 16. -
POST {{baseUrl}}/users
Content-Type: application/json
Authorization: Bearer {{token}}
{
"username": "newuser_{{$timestamp}}",
"email": "newuser{{$timestamp}}@example.com",
"password": "newpass123",
"status": 1
}
### 17. -
POST {{baseUrl}}/users
Content-Type: application/json
Authorization: Bearer {{token}}
{
"username": "admin",
"email": "admin3@example.com",
"password": "newpass123"
}
### 18. -
POST {{baseUrl}}/users
Content-Type: application/json
Authorization: Bearer {{token}}
{
"username": "incompleteuser",
"password": "newpass123"
}
### 19. -
PUT {{baseUrl}}/users/1
Content-Type: application/json
Authorization: Bearer {{token}}
{
"username": "admin_updated",
"email": "admin_updated@photography.com"
}
### 20. -
PUT {{baseUrl}}/users/99999
Content-Type: application/json
Authorization: Bearer {{token}}
{
"username": "nonexistent_user",
"email": "nonexistent@example.com"
}
### 21. -
DELETE {{baseUrl}}/users/2
Content-Type: application/json
Authorization: Bearer {{token}}
### 22. -
DELETE {{baseUrl}}/users/99999
Content-Type: application/json
Authorization: Bearer {{token}}
### 23. -
POST {{baseUrl}}/users/1/avatar
Authorization: Bearer {{token}}
Content-Type: multipart/form-data; boundary=boundary
--boundary
Content-Disposition: form-data; name="file"; filename="avatar.jpg"
Content-Type: image/jpeg
< ./test_images/avatar.jpg
--boundary--
### 24. -
POST {{baseUrl}}/users/1/avatar
Authorization: Bearer {{token}}
Content-Type: multipart/form-data; boundary=boundary
--boundary
Content-Disposition: form-data; name="title"
Test Avatar
--boundary--
### 25. -
POST {{baseUrl}}/users/1/avatar
Authorization: Bearer {{token}}
Content-Type: multipart/form-data; boundary=boundary
--boundary
Content-Disposition: form-data; name="file"; filename="document.txt"
Content-Type: text/plain
This is not an image file
--boundary--
### ===============================================
###
### ===============================================
### 26. -
GET {{baseUrl}}/categories
Content-Type: application/json
### 27. -
GET {{baseUrl}}/categories?with_count=true
Content-Type: application/json
### 28. -
GET {{baseUrl}}/categories?is_active=1
Content-Type: application/json
### 29. -
GET {{baseUrl}}/categories/1
Content-Type: application/json
### 30. -
GET {{baseUrl}}/categories/99999
Content-Type: application/json
### 31. -
POST {{baseUrl}}/categories
Content-Type: application/json
Authorization: Bearer {{token}}
{
"name": "_{{$timestamp}}",
"description": "",
"sort_order": 1,
"is_active": 1
}
### 32. -
POST {{baseUrl}}/categories
Content-Type: application/json
Authorization: Bearer {{token}}
{
"description": "",
"sort_order": 1
}
### 33. -
POST {{baseUrl}}/categories
Content-Type: application/json
Authorization: Bearer {{token}}
{
"name": "_{{$timestamp}}",
"description": "",
"parent_id": 1,
"sort_order": 1,
"is_active": 1
}
### 34. -
POST {{baseUrl}}/categories
Content-Type: application/json
Authorization: Bearer {{token}}
{
"name": "2",
"description": "",
"parent_id": 99999,
"sort_order": 1
}
### 35. -
PUT {{baseUrl}}/categories/1
Content-Type: application/json
Authorization: Bearer {{token}}
{
"name": "",
"description": "",
"sort_order": 2
}
### 36. -
PUT {{baseUrl}}/categories/99999
Content-Type: application/json
Authorization: Bearer {{token}}
{
"name": "",
"description": ""
}
### 37. -
DELETE {{baseUrl}}/categories/3
Content-Type: application/json
Authorization: Bearer {{token}}
### 38. -
DELETE {{baseUrl}}/categories/99999
Content-Type: application/json
Authorization: Bearer {{token}}
### ===============================================
###
### ===============================================
### 39. -
GET {{baseUrl}}/photos
Content-Type: application/json
### 40. -
GET {{baseUrl}}/photos?page=1&limit=5
Content-Type: application/json
### 41. -
GET {{baseUrl}}/photos?category_id=1
Content-Type: application/json
### 42. -
GET {{baseUrl}}/photos?user_id=1
Content-Type: application/json
### 43. -
GET {{baseUrl}}/photos?status=1
Content-Type: application/json
### 44. -
GET {{baseUrl}}/photos?keyword=
Content-Type: application/json
### 45. -
GET {{baseUrl}}/photos?sort=created_at_desc
Content-Type: application/json
### 46. -
GET {{baseUrl}}/photos?category_id=1&status=1&sort=title_asc&page=1&limit=10
Content-Type: application/json
### 47. -
GET {{baseUrl}}/photos/1
Content-Type: application/json
### 48. -
GET {{baseUrl}}/photos/99999
Content-Type: application/json
### 49. -
POST {{baseUrl}}/photos
Authorization: Bearer {{token}}
Content-Type: multipart/form-data; boundary=boundary
--boundary
Content-Disposition: form-data; name="file"; filename="test_photo.jpg"
Content-Type: image/jpeg
< ./test_images/test_photo.jpg
--boundary
Content-Disposition: form-data; name="title"
_{{$timestamp}}
--boundary
Content-Disposition: form-data; name="description"
--boundary
Content-Disposition: form-data; name="category_id"
1
--boundary--
### 50. -
POST {{baseUrl}}/photos
Authorization: Bearer {{token}}
Content-Type: multipart/form-data; boundary=boundary
--boundary
Content-Disposition: form-data; name="title"
--boundary
Content-Disposition: form-data; name="description"
--boundary--
### 51. -
POST {{baseUrl}}/photos
Authorization: Bearer {{token}}
Content-Type: multipart/form-data; boundary=boundary
--boundary
Content-Disposition: form-data; name="file"; filename="document.pdf"
Content-Type: application/pdf
This is not an image
--boundary
Content-Disposition: form-data; name="title"
PDF
--boundary--
### 52. -
POST {{baseUrl}}/photos
Authorization: Bearer {{token}}
Content-Type: multipart/form-data; boundary=boundary
--boundary
Content-Disposition: form-data; name="file"; filename="large_image.jpg"
Content-Type: image/jpeg
< ./test_images/large_image.jpg
--boundary
Content-Disposition: form-data; name="title"
--boundary--
### 53. -
PUT {{baseUrl}}/photos/1
Content-Type: application/json
Authorization: Bearer {{token}}
{
"title": "",
"description": "",
"category_id": 2,
"status": 1
}
### 54. -
PUT {{baseUrl}}/photos/99999
Content-Type: application/json
Authorization: Bearer {{token}}
{
"title": "",
"description": ""
}
### 55. - ()
PUT {{baseUrl}}/photos/2
Content-Type: application/json
Authorization: Bearer {{token}}
{
"title": "",
"description": ""
}
### 56. -
DELETE {{baseUrl}}/photos/1
Content-Type: application/json
Authorization: Bearer {{token}}
### 57. -
DELETE {{baseUrl}}/photos/99999
Content-Type: application/json
Authorization: Bearer {{token}}
### 58. -
DELETE {{baseUrl}}/photos/3
Content-Type: application/json
Authorization: Bearer {{token}}
### ===============================================
### 访
### ===============================================
### 59. 访
GET {{baseUrl}}/../../uploads/photos/test_image_1752197561_34895178.jpg
### 60. 访
GET {{baseUrl}}/../../uploads/photos/thumbs/test_image_1752197561_34895178_thumb.jpg
### 61. 访
GET {{baseUrl}}/../../uploads/avatars/1.jpg
### 62. 访
GET {{baseUrl}}/../../uploads/photos/nonexistent.jpg
### ===============================================
###
### ===============================================
### 63. 访
GET {{baseUrl}}/nonexistent
Content-Type: application/json
### 64. 使HTTP
POST {{baseUrl}}/health
Content-Type: application/json
### 65. JSON
POST {{baseUrl}}/auth/login
Content-Type: application/json
{
"username": "test",
"password": "test"
// JSON
}
### 66.
POST {{baseUrl}}/auth/login
Content-Type: application/json
{
"username": "test",
"password": "{{$randomWords}}{{$randomWords}}{{$randomWords}}{{$randomWords}}{{$randomWords}}{{$randomWords}}{{$randomWords}}{{$randomWords}}{{$randomWords}}{{$randomWords}}"
}
### 67. 使Token
GET {{baseUrl}}/users
Content-Type: application/json
Authorization: Bearer invalid_token_here
### 68. 使Token
GET {{baseUrl}}/users
Content-Type: application/json
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
### ===============================================
###
### ===============================================
### 69.
GET {{baseUrl}}/photos?limit=1000
Content-Type: application/json
### 70. ()
GET {{baseUrl}}/health
Content-Type: application/json
### 71.
GET {{baseUrl}}/photos?category_id=1&status=1&keyword=&sort=created_at_desc&page=1&limit=50
Content-Type: application/json
### ===============================================
###
### ===============================================
### 72. CORS
OPTIONS {{baseUrl}}/photos
Origin: http://localhost:3000
Access-Control-Request-Method: POST
Access-Control-Request-Headers: Content-Type, Authorization
### 73. CORS
GET {{baseUrl}}/photos
Origin: http://localhost:3000
### 74. CORS
GET {{baseUrl}}/photos
Origin: http://malicious-site.com
### 75. ID
GET {{baseUrl}}/health
X-Request-ID: test-request-123
### ===============================================
###
### ===============================================
### 76.
GET {{baseUrl}}/photos?keyword=
Content-Type: application/json
### 77.
GET {{baseUrl}}/photos?page=-1
Content-Type: application/json
### 78.
GET {{baseUrl}}/photos?page=0
Content-Type: application/json
### 79.
GET {{baseUrl}}/photos?page=999999
Content-Type: application/json
### 80. limit
GET {{baseUrl}}/photos?limit=10000
Content-Type: application/json
### 81. SQL
GET {{baseUrl}}/photos?keyword=' OR 1=1 --
Content-Type: application/json
### 82. XSS
POST {{baseUrl}}/categories
Content-Type: application/json
Authorization: Bearer {{token}}
{
"name": "<script>alert('xss')</script>",
"description": "XSS"
}
### ===============================================
###
### ===============================================
### 83.
POST {{baseUrl}}/auth/register
Content-Type: application/json
{
"username": "workflow_user",
"email": "workflow@example.com",
"password": "workflow123"
}
### 84. Token
POST {{baseUrl}}/auth/login
Content-Type: application/json
{
"username": "workflow_user",
"password": "workflow123"
}
### 85.
POST {{baseUrl}}/categories
Content-Type: application/json
Authorization: Bearer {{token}}
{
"name": "",
"description": ""
}
### 86.
POST {{baseUrl}}/photos
Authorization: Bearer {{token}}
Content-Type: multipart/form-data; boundary=boundary
--boundary
Content-Disposition: form-data; name="file"; filename="workflow_photo.jpg"
Content-Type: image/jpeg
< ./test_images/workflow_photo.jpg
--boundary
Content-Disposition: form-data; name="title"
--boundary
Content-Disposition: form-data; name="description"
--boundary
Content-Disposition: form-data; name="category_id"
1
--boundary--
### 87.
GET {{baseUrl}}/photos?user_id=1&keyword=
Content-Type: application/json
### 88.
PUT {{baseUrl}}/photos/1
Content-Type: application/json
Authorization: Bearer {{token}}
{
"title": "",
"description": ""
}
### 89.
GET {{baseUrl}}/photos/1
Content-Type: application/json
### ===============================================
### ()
### ===============================================
### 90.
DELETE {{baseUrl}}/photos/1
Content-Type: application/json
Authorization: Bearer {{token}}
### 91.
DELETE {{baseUrl}}/categories/1
Content-Type: application/json
Authorization: Bearer {{token}}
### 92.
DELETE {{baseUrl}}/users/2
Content-Type: application/json
Authorization: Bearer {{token}}
### ===============================================
###
### ===============================================
### -
GET {{baseUrl}}/health
Content-Type: application/json