# 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) ## 目录 1. [简介](#简介) 2. [项目结构](#项目结构) 3. [核心组件](#核心组件) 4. [架构总览](#架构总览) 5. [详细组件分析](#详细组件分析) 6. [依赖分析](#依赖分析) 7. [性能考虑](#性能考虑) 8. [故障排查指南](#故障排查指南) 9. [结论](#结论) 10. [附录](#附录) ## 简介 本API参考面向CarrotSkin后端服务,覆盖认证、用户、材质、档案、验证码、Yggdrasil与系统配置等API组。文档基于routes.go与swagger.go中的路由与注释,结合各处理器文件的注释与类型定义,提供: - 端点清单与HTTP方法、URL模式 - 请求/响应模式与鉴权要求(JWT) - 错误码与常见错误场景 - 参数校验规则与示例 - 性能优化建议与最佳实践 ## 项目结构 - 路由注册集中在路由文件,按版本分组与鉴权中间件组合 - Swagger文档与健康检查在统一入口启用 - 各功能模块处理器文件通过注释提供OpenAPI规范 - 中间件负责JWT鉴权与可选鉴权 - 响应模型与类型定义集中于model与types目录 ```mermaid graph TB A["Gin引擎"] --> B["Swagger文档
/swagger/*any"] A --> C["健康检查
/health"] A --> D["API v1 组
/api/v1"] D --> E["认证组
/api/v1/auth/*"] D --> F["用户组
/api/v1/user/*"] D --> G["材质组
/api/v1/texture/*"] D --> H["档案组
/api/v1/profile/*"] D --> I["验证码组
/api/v1/captcha/*"] D --> J["Yggdrasil组
/api/v1/yggdrasil/*"] D --> K["系统组
/api/v1/system/*"] ``` 图表来源 - [routes.go](file://internal/handler/routes.go#L10-L118) - [swagger.go](file://internal/handler/swagger.go#L41-L63) 章节来源 - [routes.go](file://internal/handler/routes.go#L10-L118) - [swagger.go](file://internal/handler/swagger.go#L41-L63) ## 核心组件 - 路由注册器:按版本分组,按需挂载鉴权中间件 - Swagger:提供交互式文档与健康检查 - 鉴权中间件:统一从Authorization头解析Bearer Token并注入用户上下文 - 响应模型:统一的响应结构与分页结构 - 类型定义:请求/响应结构体与约束规则 章节来源 - [routes.go](file://internal/handler/routes.go#L10-L118) - [swagger.go](file://internal/handler/swagger.go#L41-L63) - [auth.go](file://internal/middleware/auth.go#L12-L56) - [response.go](file://internal/model/response.go#L1-L86) - [common.go](file://internal/types/common.go#L1-L215) ## 架构总览 下图展示API调用链与鉴权流程: ```mermaid 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 : "统一响应结构" ``` 图表来源 - [auth.go](file://internal/middleware/auth.go#L12-L56) - [routes.go](file://internal/handler/routes.go#L10-L118) ## 详细组件分析 ### 认证组(/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(参数错误) 参数与校验要点 - RegisterRequest:用户名、邮箱、密码、验证码、可选头像URL - LoginRequest:用户名或邮箱、密码 - SendVerificationCodeRequest:邮箱、类型 - ResetPasswordRequest:邮箱、验证码、新密码 章节来源 - [routes.go](file://internal/handler/routes.go#L18-L25) - [auth_handler.go](file://internal/handler/auth_handler.go#L17-L84) - [auth_handler.go](file://internal/handler/auth_handler.go#L86-L147) - [auth_handler.go](file://internal/handler/auth_handler.go#L149-L192) - [auth_handler.go](file://internal/handler/auth_handler.go#L194-L249) - [common.go](file://internal/types/common.go#L27-L66) ### 用户组(/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](file://internal/handler/routes.go#L27-L41) - [user_handler.go](file://internal/handler/user_handler.go#L17-L68) - [user_handler.go](file://internal/handler/user_handler.go#L70-L193) - [user_handler.go](file://internal/handler/user_handler.go#L195-L253) - [user_handler.go](file://internal/handler/user_handler.go#L255-L326) - [user_handler.go](file://internal/handler/user_handler.go#L328-L416) - [common.go](file://internal/types/common.go#L42-L80) - [common.go](file://internal/types/common.go#L107-L125) - [common.go](file://internal/types/common.go#L167-L179) ### 材质组(/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 - 需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) 参数与校验要点 - GenerateTextureUploadURLRequest:文件名必填、类型枚举(SKIN/CAPE) - CreateTextureRequest:名称必填、URL必填且为有效URL、哈希长度64、大小>0、类型枚举 - UpdateTextureRequest:名称长度限制、公开性可选 - 搜索与分页:默认page=1、page_size默认20、最大100 章节来源 - [routes.go](file://internal/handler/routes.go#L42-L61) - [texture_handler.go](file://internal/handler/texture_handler.go#L18-L83) - [texture_handler.go](file://internal/handler/texture_handler.go#L85-L172) - [texture_handler.go](file://internal/handler/texture_handler.go#L174-L223) - [texture_handler.go](file://internal/handler/texture_handler.go#L225-L291) - [texture_handler.go](file://internal/handler/texture_handler.go#L293-L369) - [texture_handler.go](file://internal/handler/texture_handler.go#L371-L419) - [texture_handler.go](file://internal/handler/texture_handler.go#L421-L471) - [texture_handler.go](file://internal/handler/texture_handler.go#L473-L599) - [common.go](file://internal/types/common.go#L81-L105) - [common.go](file://internal/types/common.go#L181-L191) - [common.go](file://internal/types/common.go#L193-L200) ### 档案组(/api/v1/profile) - 公开端点(无需JWT) - GET /api/v1/profile/{uuid} - 路径参数:uuid - 响应:ProfileInfo - 错误:404(档案不存在)、500(服务器错误) - 需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(服务器错误) 参数与校验要点 - CreateProfileRequest:名称长度1-16 - UpdateProfileRequest:名称长度1-16,皮肤/斗篷ID可选 章节来源 - [routes.go](file://internal/handler/routes.go#L63-L79) - [profile_handler.go](file://internal/handler/profile_handler.go#L15-L93) - [profile_handler.go](file://internal/handler/profile_handler.go#L95-L151) - [profile_handler.go](file://internal/handler/profile_handler.go#L153-L195) - [profile_handler.go](file://internal/handler/profile_handler.go#L197-L280) - [profile_handler.go](file://internal/handler/profile_handler.go#L282-L339) - [profile_handler.go](file://internal/handler/profile_handler.go#L341-L399) - [common.go](file://internal/types/common.go#L81-L85) - [common.go](file://internal/types/common.go#L201-L207) ### 验证码组(/api/v1/captcha) - GET /api/v1/captcha/generate - 响应:主图、滑块图、验证码ID、Y坐标 - 错误:500(生成失败) - POST /api/v1/captcha/verify - 请求体:{captchaId, dx} - 响应:验证结果(成功/失败) - 错误:400(参数错误)、500(验证失败) 章节来源 - [routes.go](file://internal/handler/routes.go#L80-L85) - [captcha_handler.go](file://internal/handler/captcha_handler.go#L11-L34) - [captcha_handler.go](file://internal/handler/captcha_handler.go#L36-L77) ### Yggdrasil组(/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 - 会话服务 - 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(无内容) - API服务 - POST /api/v1/yggdrasil/api/profiles/minecraft - 请求体:字符串数组(玩家名) - 响应:Profile列表 参数与校验要点 - 认证/验证/刷新/登出:均需严格校验请求体字段与类型 - 会话验证:serverId与username必填 - 批量查询:名称数组非空 章节来源 - [routes.go](file://internal/handler/routes.go#L87-L111) - [yggdrasil_handler.go](file://internal/handler/yggdrasil_handler.go#L156-L246) - [yggdrasil_handler.go](file://internal/handler/yggdrasil_handler.go#L248-L267) - [yggdrasil_handler.go](file://internal/handler/yggdrasil_handler.go#L269-L361) - [yggdrasil_handler.go](file://internal/handler/yggdrasil_handler.go#L363-L378) - [yggdrasil_handler.go](file://internal/handler/yggdrasil_handler.go#L380-L425) - [yggdrasil_handler.go](file://internal/handler/yggdrasil_handler.go#L427-L447) - [yggdrasil_handler.go](file://internal/handler/yggdrasil_handler.go#L449-L496) - [yggdrasil_handler.go](file://internal/handler/yggdrasil_handler.go#L498-L552) - [yggdrasil_handler.go](file://internal/handler/yggdrasil_handler.go#L554-L587) - [yggdrasil_handler.go](file://internal/handler/yggdrasil_handler.go#L589-L616) - [yggdrasil_handler.go](file://internal/handler/yggdrasil_handler.go#L618-L666) ### 系统组(/api/v1/system) - GET /api/v1/system/config - 响应:站点名称、描述、注册开关、每用户最大材质数、每用户最大档案数 - 注意:当前实现为占位返回固定配置 章节来源 - [routes.go](file://internal/handler/routes.go#L112-L118) - [routes.go](file://internal/handler/routes.go#L120-L140) ## 依赖分析 - 路由与中间件 - 路由文件按组挂载鉴权中间件,确保受保护端点仅接受有效JWT - 处理器与服务 - 处理器通过服务层完成业务逻辑,服务层再与数据库/缓存交互 - 响应与类型 - 统一响应结构与分页结构,类型定义集中约束参数范围与格式 ```mermaid graph LR Routes["路由注册
routes.go"] --> MW["鉴权中间件
auth.go"] MW --> Handlers["各处理器
auth/user/texture/profile/captcha/yggdrasil"] Handlers --> Services["服务层"] Services --> DB["数据库/缓存"] Handlers --> Models["响应模型
response.go"] Handlers --> Types["类型定义
common.go"] ``` 图表来源 - [routes.go](file://internal/handler/routes.go#L10-L118) - [auth.go](file://internal/middleware/auth.go#L12-L56) - [response.go](file://internal/model/response.go#L1-L86) - [common.go](file://internal/types/common.go#L1-L215) 章节来源 - [routes.go](file://internal/handler/routes.go#L10-L118) - [auth.go](file://internal/middleware/auth.go#L12-L56) - [response.go](file://internal/model/response.go#L1-L86) - [common.go](file://internal/types/common.go#L1-L215) ## 性能考虑 - 上传URL预签名 - 材质与头像上传URL均采用预签名策略,缩短上传路径、降低后端压力 - 分页与限制 - 材质与档案列表默认分页,避免一次性返回大量数据 - 材质与档案数量限制(当前代码中硬编码,建议从配置读取) - 缓存与日志 - Redis用于验证码与公钥等缓存,减少数据库压力 - 日志记录关键错误,便于追踪与优化 - 并发与超时 - 建议为外部服务(如对象存储)设置合理超时与重试策略 ## 故障排查指南 - 鉴权失败 - 缺少Authorization头或格式不正确(401) - 无效token(401) - 参数错误 - JSON绑定失败或字段校验不通过(400) - 资源不存在 - 用户、档案、材质不存在(404) - 权限不足 - 非本人操作(403) - 服务器错误 - 数据库异常、外部服务不可用(500) 章节来源 - [auth.go](file://internal/middleware/auth.go#L12-L56) - [response.go](file://internal/model/response.go#L27-L52) - [auth_handler.go](file://internal/handler/auth_handler.go#L17-L84) - [user_handler.go](file://internal/handler/user_handler.go#L70-L193) - [texture_handler.go](file://internal/handler/texture_handler.go#L225-L291) - [profile_handler.go](file://internal/handler/profile_handler.go#L197-L280) ## 结论 本API参考基于现有路由与处理器注释,梳理了CarrotSkin后端的核心REST接口与鉴权机制。建议在生产环境中: - 将硬编码限制与默认值迁移至配置中心 - 引入速率限制与防刷策略 - 对敏感接口增加审计日志 - 完善单元测试与集成测试覆盖 ## 附录 ### 统一响应结构 - 成功响应:包含code、message、data - 分页响应:包含code、message、data、total、page、per_page - 错误响应:包含code、message、error(开发环境) 章节来源 - [response.go](file://internal/model/response.go#L1-L86) ### 常见错误码 - 200:成功 - 400:请求参数错误 - 401:未授权 - 403:禁止访问 - 404:资源不存在 - 500:服务器内部错误 章节来源 - [response.go](file://internal/model/response.go#L27-L52) ### Swagger与健康检查 - 文档地址:/swagger/*any - 健康检查:/health 章节来源 - [swagger.go](file://internal/handler/swagger.go#L41-L63)