Some checks failed
Build and Push Docker Image / build-and-push (push) Failing after 15m39s
- 修复 AuthContext 硬编码 localhost:8080,改用 api.ts 统一的 API_BASE_URL(走环境变量/代理,生产可部署) - 修复注册页发送验证码绕过 api.ts 直接 raw fetch 的问题,改用统一的 sendVerificationCode - 修复 SliderCaptcha 验证成功后 captchaId 未透传导致注册人机验证失效的断链 - 修复头像上传契约:预签名URL方式(/user/avatar/upload-url)改为直传(/user/avatar/upload) - 移除后端不支持的'设置活跃角色'功能(/profile/:uuid/activate)及相关死代码 - 修复分页字段不一致:新增 normalizePaginatedData 兼容后端 per_page 响应 - 强化邮箱正则校验(RFC 标准,禁止连续点/首尾点,TLD>=2字母) - 移除首页指向无效 /api 页面的'查看API文档'按钮 - 新增 /register /login /signup 重定向路由,统一指向 /auth?mode= - 同步 API文档.md
9.2 KiB
9.2 KiB
CarrotSkin API 文档(基于后端代码,2026-07 修订)
本文档由后端
internal/handler/*.go+internal/types/common.go直接整理而来, 是前后端契约的唯一事实来源。所有路径以/api/v1为前缀(Yggdrasil / CSL 除外)。
通用约定
统一响应格式
成功:
{ "code": 200, "message": "操作成功", "data": <任意> }
错误:
{ "code": <非200>, "message": "<错误描述>", "error": "<仅非生产环境返回>" }
常用状态码:200 成功 / 201 创建成功 / 400 参数错误 / 401 未授权 / 403 禁止 / 404 不存在 / 500 服务器错误。
认证
- 除"无需认证"标注的接口外,所有
/user/*、/profile写操作、/texture写操作均需在请求头携带:Authorization: Bearer <jwt_token> - JWT 通过登录或注册接口获取。
分页
- 请求参数:
page(页码,默认 1)、page_size(每页数量,默认 20)。 - 响应数据形态(注意:后端返回的字段名是
per_page,且 不含total_pages):
{
"code": 200,
"message": "操作成功",
"data": {
"list": [ ... ],
"total": 100,
"page": 1,
"per_page": 20
}
}
一、认证 /auth(无需 JWT)
1. 用户注册
POST /api/v1/auth/register- Body:
{
"username": "newuser",
"email": "user@example.com",
"password": "password123",
"verification_code": "123456",
"captcha_id": "uuid-xxxx",
"avatar": "https://example.com/a.png"
}
username3–50 字符;password6–128;verification_code必填 6 位;captcha_id必填(来自POST /captcha/verify后透传的captchaId);avatar可选,必须是合法 URL。- 响应
data:
{
"token": "<jwt>",
"user_info": {
"id": 1, "username": "newuser", "email": "user@example.com",
"avatar": "", "points": 0, "role": "user", "status": 1,
"last_login_at": null,
"created_at": "2026-07-08T10:00:00Z",
"updated_at": "2026-07-08T10:00:00Z"
}
}
2. 用户登录
POST /api/v1/auth/login- Body:
{ "username": "newuser 或 user@example.com", "password": "password123" }
- 响应
data:同注册({ token, user_info })。
3. 发送邮箱验证码
POST /api/v1/auth/send-code- Body:
{ "email": "user@example.com", "type": "register | reset_password | change_email" }
- 响应
data:{ "message": "验证码已发送,请查收邮件" }。
4. 重置密码
POST /api/v1/auth/reset-password- Body:
{
"email": "user@example.com",
"verification_code": "123456",
"new_password": "newpassword123"
}
- 响应
data:{ "message": "密码重置成功" }。
二、用户 /user(需 JWT)
5. 获取当前用户信息
GET /api/v1/user/profile- 响应
data:UserInfo(同注册返回的user_info)。
6. 更新用户信息(密码 / 头像 URL)
PUT /api/v1/user/profile- Body:
{
"avatar": "https://example.com/a.png", // 可选,更新头像 URL
"old_password": "oldpassword123", // 修改密码时必填
"new_password": "newpassword123" // 6–128
}
- 响应
data:更新后的UserInfo。
7. 上传头像文件
POST /api/v1/user/avatar/upload(multipart/form-data)- 字段:
file(图片文件,≤10MB) - 响应
data:
{ "avatar_url": "https://.../avatar.png", "user": { ...UserInfo } }
8. 更新头像 URL(外部 URL)
PUT /api/v1/user/avatar?avatar_url=<url>- 响应
data:UserInfo。
9. 更换邮箱
POST /api/v1/user/change-email- Body:
{ "new_email": "new@example.com", "verification_code": "123456" }
- 响应
data:更换后的UserInfo(新邮箱已生效)。
10. 重置 Yggdrasil 密码
POST /api/v1/user/yggdrasil-password/reset- 响应
data:{ "password": "<新的Yggdrasil密码>" }。
11. 获取用户公开信息
GET /api/v1/users/public?username=<name>或?id=<id>(无需 JWT)- 响应
data:
{
"id": 1, "username": "testuser", "avatar": "",
"points": 100, "role": "user", "status": 1,
"created_at": "2026-07-01T10:00:00Z"
}
三、材质 /texture
12. 搜索材质(公开,无需 JWT)
GET /api/v1/texture- Query:
keyword/type=SKIN|CAPE/public_only=true/page/page_size - 响应
data:分页结构{ list: TextureInfo[], total, page, per_page }。
13. 获取材质详情(公开)
GET /api/v1/texture/:id- 响应
data:TextureInfo。
14. 上传材质(需 JWT,multipart)
POST /api/v1/texture/upload- formData:
file(PNG, ≤32MB)、name(必填)、description、type=SKIN|CAPE、is_public、is_slim - 响应
data:TextureInfo。
15. 更新材质(需 JWT)
PUT /api/v1/texture/:id- Body:
{ "name": "新名称", "description": "新描述", "is_public": true }
is_public后端为*bool,传true/false会更新;不传保持不变。- 响应
data:TextureInfo。
16. 删除材质(需 JWT)
DELETE /api/v1/texture/:id- 响应
data:null。
17. 切换收藏(需 JWT)
POST /api/v1/texture/:id/favorite- 响应
data:{ "is_favorited": true }。
18. 我的上传(需 JWT)
GET /api/v1/texture/my?page=1&page_size=20- 响应
data:分页结构。
19. 我的收藏(需 JWT)
GET /api/v1/texture/favorites?page=1&page_size=20- 响应
data:分页结构。
TextureInfo 字段
id, uploader_id, uploader_username, name, description(omitempty), type(SKIN|CAPE), url, hash, size, is_public, download_count, favorite_count, is_slim, status, created_at, updated_at
四、档案 /profile
⚠️ 后端当前
PUT /profile/:uuid不支持解除皮肤/披风绑定:UpdateProfileRequest.SkinID / CapeID为*int64,仅当非 nil 时才更新; 传null与字段缺失都会被 Go 反序列化为nil,二者无法区分,均被忽略。 因此前端要"移除角色皮肤",需要后端先支持(详见下方《待补齐》)。
20. 获取档案列表(需 JWT)
GET /api/v1/profile或GET /api/v1/profile/- 响应
data:ProfileInfo[]。
21. 创建档案(需 JWT)
POST /api/v1/profile或POST /api/v1/profile/- Body:
{ "name": "PlayerName" }(1–16 字符) - 响应
data:ProfileInfo。
22. 获取档案详情(公开)
GET /api/v1/profile/:uuid- 响应
data:ProfileInfo。
23. 更新档案(需 JWT)
PUT /api/v1/profile/:uuid- Body:
{ "name": "NewName", "skin_id": 1, "cape_id": 2 }
- 当前实现:
skin_id/cape_id传数字会设置;传 null / 缺失均被忽略(无法清空)。 - 响应
data:ProfileInfo。
24. 删除档案(需 JWT)
DELETE /api/v1/profile/:uuid- 响应
data:{ "message": "删除成功" }。
ProfileInfo 字段
uuid, user_id, name, skin_id(omitempty,可空), cape_id(omitempty,可空), last_used_at(omitempty), created_at, updated_at
五、滑动验证码 /captcha(无需 JWT)
25. 生成滑动验证码
GET /api/v1/captcha/generate- 响应(注意:此接口的响应是直接对象,未包裹
data):
{
"code": 200,
"data": {
"masterImage": "<base64 主图>",
"tileImage": "<base64 滑块图>",
"captchaId": "<进程ID,注册时需要>",
"y": <缺口纵坐标>
}
}
26. 校验滑动验证码
POST /api/v1/captcha/verify- Body:
{ "captchaId": "<id>", "dx": <横坐标> } - 响应:
{ "code": 200, "msg": "验证成功" }或{ "code": 400, "msg": "验证失败,请重试" }
六、Yggdrasil API /api/yggdrasil(独立前缀,供 MC 客户端使用)
GET /api/yggdrasil—— 元数据POST /api/yggdrasil/minecraftservices/player/certificatesPOST /api/yggdrasil/authserver/authenticatePOST /api/yggdrasil/authserver/validatePOST /api/yggdrasil/authserver/refreshPOST /api/yggdrasil/authserver/invalidatePOST /api/yggdrasil/authserver/signoutGET /api/yggdrasil/sessionserver/session/minecraft/profile/:uuidPOST /api/yggdrasil/sessionserver/session/minecraft/joinGET /api/yggdrasil/sessionserver/session/minecraft/hasJoinedPOST /api/yggdrasil/api/profiles/minecraft
七、CustomSkinAPI /api/v1/csl(公开)
GET /api/v1/csl/:username—— 获取玩家信息 JSONGET /api/v1/csl/textures/:hash—— 获取资源文件
八、管理员 /api/v1/admin(需 JWT + 管理员)
GET /admin/users、GET /admin/users/:idPUT /admin/users/role、PUT /admin/users/statusGET /admin/textures、DELETE /admin/textures/:idGET /admin/permissions
待补齐(后端缺陷,影响前端可用性)
PUT /profile/:uuid不支持清空 skin/cape 现状:SkinID/CapeID *int64无法区分"未传"与"显式 null"。 建议:改用json.RawMessage区分三种语义(缺失=不修改 / null=清空 / 数字=设置), 或新增remove_skin/remove_cape布尔字段。前端"移除角色皮肤"依赖此能力。