19 KiB
19 KiB
API参考
**本文引用的文件** - [routes.go](file://internal/handler/routes.go) - [swagger.go](file://internal/handler/swagger.go) - [auth_handler.go](file://internal/handler/auth_handler.go) - [user_handler.go](file://internal/handler/user_handler.go) - [texture_handler.go](file://internal/handler/texture_handler.go) - [profile_handler.go](file://internal/handler/profile_handler.go) - [captcha_handler.go](file://internal/handler/captcha_handler.go) - [yggdrasil_handler.go](file://internal/handler/yggdrasil_handler.go) - [auth.go](file://internal/middleware/auth.go) - [response.go](file://internal/model/response.go) - [common.go](file://internal/types/common.go)目录
简介
本API参考面向CarrotSkin后端服务,覆盖认证、用户、材质、档案、验证码、Yggdrasil与系统配置等API组。文档基于routes.go与swagger.go中的路由与注释,结合各处理器文件的注释与类型定义,提供:
- 端点清单与HTTP方法、URL模式
- 请求/响应模式与鉴权要求(JWT)
- 错误码与常见错误场景
- 参数校验规则与示例
- 性能优化建议与最佳实践
项目结构
- 路由注册集中在路由文件,按版本分组与鉴权中间件组合
- Swagger文档与健康检查在统一入口启用
- 各功能模块处理器文件通过注释提供OpenAPI规范
- 中间件负责JWT鉴权与可选鉴权
- 响应模型与类型定义集中于model与types目录
graph TB
A["Gin引擎"] --> B["Swagger文档<br/>/swagger/*any"]
A --> C["健康检查<br/>/health"]
A --> D["API v1 组<br/>/api/v1"]
D --> E["认证组<br/>/api/v1/auth/*"]
D --> F["用户组<br/>/api/v1/user/*"]
D --> G["材质组<br/>/api/v1/texture/*"]
D --> H["档案组<br/>/api/v1/profile/*"]
D --> I["验证码组<br/>/api/v1/captcha/*"]
D --> J["Yggdrasil组<br/>/api/v1/yggdrasil/*"]
D --> K["系统组<br/>/api/v1/system/*"]
图表来源
章节来源
核心组件
- 路由注册器:按版本分组,按需挂载鉴权中间件
- Swagger:提供交互式文档与健康检查
- 鉴权中间件:统一从Authorization头解析Bearer Token并注入用户上下文
- 响应模型:统一的响应结构与分页结构
- 类型定义:请求/响应结构体与约束规则
章节来源
架构总览
下图展示API调用链与鉴权流程:
sequenceDiagram
participant Client as "客户端"
participant Router as "Gin路由"
participant MW as "鉴权中间件"
participant Handler as "处理器"
participant Service as "服务层"
participant DB as "数据库/缓存"
Client->>Router : "HTTP请求"
Router->>MW : "匹配路由并执行中间件"
MW->>MW : "解析Authorization头"
MW->>MW : "校验JWT并注入用户上下文"
MW-->>Router : "通过或拒绝"
Router->>Handler : "转发到对应处理器"
Handler->>Service : "调用业务逻辑"
Service->>DB : "读写数据"
DB-->>Service : "返回结果"
Service-->>Handler : "返回业务结果"
Handler-->>Client : "统一响应结构"
图表来源
详细组件分析
认证组(/api/v1/auth)
- 无需JWT
- 端点
- POST /api/v1/auth/register
- 请求体:RegisterRequest
- 响应:LoginResponse(含token与用户信息)
- 错误:400(参数错误)、401(登录失败)
- POST /api/v1/auth/login
- 请求体:LoginRequest(支持用户名或邮箱)
- 响应:LoginResponse
- 错误:400(参数错误)、401(登录失败)
- POST /api/v1/auth/send-code
- 请求体:SendVerificationCodeRequest(类型枚举:register/reset_password/change_email)
- 响应:通用成功响应
- 错误:400(参数错误)
- POST /api/v1/auth/reset-password
- 请求体:ResetPasswordRequest(验证码6位)
- 响应:通用成功响应
- 错误:400(参数错误)
- POST /api/v1/auth/register
参数与校验要点
- RegisterRequest:用户名、邮箱、密码、验证码、可选头像URL
- LoginRequest:用户名或邮箱、密码
- SendVerificationCodeRequest:邮箱、类型
- ResetPasswordRequest:邮箱、验证码、新密码
章节来源
用户组(/api/v1/user,需JWT)
- GET /api/v1/user/profile
- 响应:UserInfo
- 错误:401(未授权)、404(用户不存在)
- PUT /api/v1/user/profile
- 请求体:UpdateUserRequest(修改密码需同时提供旧密码与新密码)
- 响应:UserInfo
- 错误:400(参数错误)、401(未授权)、404(用户不存在)、500(服务器错误)
- POST /api/v1/user/avatar/upload-url
- 请求体:GenerateAvatarUploadURLRequest(文件名)
- 响应:GenerateAvatarUploadURLResponse(含post_url、form_data、avatar_url、expires_in)
- 错误:400(参数错误)
- PUT /api/v1/user/avatar
- 查询参数:avatar_url
- 响应:UserInfo
- 错误:400(参数错误)
- POST /api/v1/user/change-email
- 请求体:ChangeEmailRequest(新邮箱+验证码)
- 响应:UserInfo
- 错误:400(参数错误)、401(未授权)
参数与校验要点
- UpdateUserRequest:头像URL、旧密码、新密码(二者需同时提供)
- GenerateAvatarUploadURLRequest:文件名必填
- ChangeEmailRequest:新邮箱、验证码
章节来源
- routes.go
- user_handler.go
- user_handler.go
- user_handler.go
- user_handler.go
- user_handler.go
- common.go
- common.go
- common.go
材质组(/api/v1/texture)
- 公开端点(无需JWT)
- GET /api/v1/texture
- 查询:keyword、type(SKIN/CAPE)、public_only、page、page_size
- 响应:分页响应(列表项为TextureInfo)
- GET /api/v1/texture/{id}
- 路径参数:id
- 响应:TextureInfo
- GET /api/v1/texture
- 需JWT端点
- POST /api/v1/texture/upload-url
- 请求体:GenerateTextureUploadURLRequest(文件名、纹理类型)
- 响应:GenerateTextureUploadURLResponse(含post_url、form_data、texture_url、expires_in)
- 错误:400(参数错误)
- POST /api/v1/texture
- 请求体:CreateTextureRequest(名称、描述、类型、URL、哈希、大小、公开性、是否Slim)
- 响应:TextureInfo
- 错误:400(参数错误)
- PUT /api/v1/texture/{id}
- 路径参数:id;请求体:UpdateTextureRequest(名称、描述、公开性)
- 响应:TextureInfo
- 错误:400(参数错误)、403(无权操作)
- DELETE /api/v1/texture/{id}
- 路径参数:id
- 响应:通用成功响应
- 错误:400(参数错误)、403(无权操作)
- POST /api/v1/texture/{id}/favorite
- 路径参数:id
- 响应:布尔值(是否收藏)
- 错误:400(参数错误)
- GET /api/v1/texture/my
- 查询:page、page_size
- 响应:分页响应(列表项为TextureInfo)
- GET /api/v1/texture/favorites
- 查询:page、page_size
- 响应:分页响应(列表项为TextureInfo)
- POST /api/v1/texture/upload-url
参数与校验要点
- GenerateTextureUploadURLRequest:文件名必填、类型枚举(SKIN/CAPE)
- CreateTextureRequest:名称必填、URL必填且为有效URL、哈希长度64、大小>0、类型枚举
- UpdateTextureRequest:名称长度限制、公开性可选
- 搜索与分页:默认page=1、page_size默认20、最大100
章节来源
- routes.go
- texture_handler.go
- texture_handler.go
- texture_handler.go
- texture_handler.go
- texture_handler.go
- texture_handler.go
- texture_handler.go
- texture_handler.go
- common.go
- common.go
- common.go
档案组(/api/v1/profile)
- 公开端点(无需JWT)
- GET /api/v1/profile/{uuid}
- 路径参数:uuid
- 响应:ProfileInfo
- 错误:404(档案不存在)、500(服务器错误)
- GET /api/v1/profile/{uuid}
- 需JWT端点
- POST /api/v1/profile
- 请求体:CreateProfileRequest(名称)
- 响应:ProfileInfo(含自动生成UUID)
- 错误:400(参数错误或已达上限)、401(未授权)、500(服务器错误)
- GET /api/v1/profile
- 响应:ProfileInfo列表
- 错误:401(未授权)、500(服务器错误)
- PUT /api/v1/profile/{uuid}
- 路径参数:uuid;请求体:UpdateProfileRequest(名称、皮肤ID、斗篷ID)
- 响应:ProfileInfo
- 错误:400(参数错误)、401(未授权)、403(无权操作)、404(档案不存在)、500(服务器错误)
- DELETE /api/v1/profile/{uuid}
- 路径参数:uuid
- 响应:通用成功响应
- 错误:401(未授权)、403(无权操作)、404(档案不存在)、500(服务器错误)
- POST /api/v1/profile/{uuid}/activate
- 路径参数:uuid
- 响应:通用成功响应
- 错误:401(未授权)、403(无权操作)、404(档案不存在)、500(服务器错误)
- POST /api/v1/profile
参数与校验要点
- CreateProfileRequest:名称长度1-16
- UpdateProfileRequest:名称长度1-16,皮肤/斗篷ID可选
章节来源
- routes.go
- profile_handler.go
- profile_handler.go
- profile_handler.go
- profile_handler.go
- profile_handler.go
- profile_handler.go
- common.go
- common.go
验证码组(/api/v1/captcha)
- GET /api/v1/captcha/generate
- 响应:主图、滑块图、验证码ID、Y坐标
- 错误:500(生成失败)
- POST /api/v1/captcha/verify
- 请求体:{captchaId, dx}
- 响应:验证结果(成功/失败)
- 错误:400(参数错误)、500(验证失败)
章节来源
Yggdrasil组(/api/v1/yggdrasil)
- 元数据
- GET /api/v1/yggdrasil
- 响应:实现信息、链接、特性开关、签名公钥、皮肤域名
- GET /api/v1/yggdrasil
- 认证服务
- POST /api/v1/yggdrasil/authserver/authenticate
- 请求体:AuthenticateRequest(agent、clientToken、identifier、password、requestUser)
- 响应:AccessToken、ClientToken、SelectedProfile、AvailableProfiles、User(可选)
- POST /api/v1/yggdrasil/authserver/validate
- 请求体:ValidTokenRequest(accessToken、clientToken)
- 响应:204(有效)或403(无效)
- POST /api/v1/yggdrasil/authserver/refresh
- 请求体:RefreshRequest(accessToken、clientToken、requestUser、selectedProfile)
- 响应:新的AccessToken、ClientToken、SelectedProfile、User(可选)
- POST /api/v1/yggdrasil/authserver/invalidate
- 请求体:ValidTokenRequest(accessToken、clientToken)
- 响应:204
- POST /api/v1/yggdrasil/authserver/signout
- 请求体:SignOutRequest(username、password)
- 响应:204
- POST /api/v1/yggdrasil/authserver/authenticate
- 会话服务
- GET /api/v1/yggdrasil/sessionserver/session/minecraft/profile/{uuid}
- 响应:序列化后的档案信息
- POST /api/v1/yggdrasil/sessionserver/session/minecraft/join
- 请求体:JoinServerRequest(serverId、accessToken、selectedProfile)
- 响应:204 或错误
- GET /api/v1/yggdrasil/sessionserver/session/minecraft/hasJoined
- 查询:serverId、username、ip
- 响应:200(Profile)或204(无内容)
- GET /api/v1/yggdrasil/sessionserver/session/minecraft/profile/{uuid}
- API服务
- POST /api/v1/yggdrasil/api/profiles/minecraft
- 请求体:字符串数组(玩家名)
- 响应:Profile列表
- POST /api/v1/yggdrasil/api/profiles/minecraft
参数与校验要点
- 认证/验证/刷新/登出:均需严格校验请求体字段与类型
- 会话验证:serverId与username必填
- 批量查询:名称数组非空
章节来源
- routes.go
- yggdrasil_handler.go
- yggdrasil_handler.go
- yggdrasil_handler.go
- yggdrasil_handler.go
- yggdrasil_handler.go
- yggdrasil_handler.go
- yggdrasil_handler.go
- yggdrasil_handler.go
- yggdrasil_handler.go
- yggdrasil_handler.go
- yggdrasil_handler.go
系统组(/api/v1/system)
- GET /api/v1/system/config
- 响应:站点名称、描述、注册开关、每用户最大材质数、每用户最大档案数
- 注意:当前实现为占位返回固定配置
章节来源
依赖分析
- 路由与中间件
- 路由文件按组挂载鉴权中间件,确保受保护端点仅接受有效JWT
- 处理器与服务
- 处理器通过服务层完成业务逻辑,服务层再与数据库/缓存交互
- 响应与类型
- 统一响应结构与分页结构,类型定义集中约束参数范围与格式
graph LR
Routes["路由注册<br/>routes.go"] --> MW["鉴权中间件<br/>auth.go"]
MW --> Handlers["各处理器<br/>auth/user/texture/profile/captcha/yggdrasil"]
Handlers --> Services["服务层"]
Services --> DB["数据库/缓存"]
Handlers --> Models["响应模型<br/>response.go"]
Handlers --> Types["类型定义<br/>common.go"]
图表来源
章节来源
性能考虑
- 上传URL预签名
- 材质与头像上传URL均采用预签名策略,缩短上传路径、降低后端压力
- 分页与限制
- 材质与档案列表默认分页,避免一次性返回大量数据
- 材质与档案数量限制(当前代码中硬编码,建议从配置读取)
- 缓存与日志
- Redis用于验证码与公钥等缓存,减少数据库压力
- 日志记录关键错误,便于追踪与优化
- 并发与超时
- 建议为外部服务(如对象存储)设置合理超时与重试策略
故障排查指南
- 鉴权失败
- 缺少Authorization头或格式不正确(401)
- 无效token(401)
- 参数错误
- JSON绑定失败或字段校验不通过(400)
- 资源不存在
- 用户、档案、材质不存在(404)
- 权限不足
- 非本人操作(403)
- 服务器错误
- 数据库异常、外部服务不可用(500)
章节来源
结论
本API参考基于现有路由与处理器注释,梳理了CarrotSkin后端的核心REST接口与鉴权机制。建议在生产环境中:
- 将硬编码限制与默认值迁移至配置中心
- 引入速率限制与防刷策略
- 对敏感接口增加审计日志
- 完善单元测试与集成测试覆盖
附录
统一响应结构
- 成功响应:包含code、message、data
- 分页响应:包含code、message、data、total、page、per_page
- 错误响应:包含code、message、error(开发环境)
章节来源
常见错误码
- 200:成功
- 400:请求参数错误
- 401:未授权
- 403:禁止访问
- 404:资源不存在
- 500:服务器内部错误
章节来源
Swagger与健康检查
- 文档地址:/swagger/*any
- 健康检查:/health
章节来源