feat: API 基建——/api JSON 接口统一契约与认证分支

- handlers/api.go:APIOK/APIError/bindJSON,统一 {ok,redirect,data} /
  {ok:false,code,error} 响应契约(code=i18n 键,error 按请求语言翻译)
- i18n:新增 api_error/api_unauthorized/api_forbidden/api_invalid_request(中英)
- middleware/auth.go:AuthRequired/AdminRequired 按 /api 前缀分支:
  JSON 401/403(页面保持 302),新增 isAPIRequest + apiAuthError
- main.go:路由注册提取为 registerRoutes;建立 /api 分组并搬移附件三件套
  (admin/my)与 /api/profile/avatar(旧 /admin|my/articles/attachments、
  /profile/avatar 路由移除)
- handlers/login_ratelimit.go:loginRateLimiter 导出为 LoginRateLimiter
- templates/layouts/base.html:blogAPI/blogForm/blogShowError 共享 fetch 助手
- main_test.go:TestRegisterRoutesSmoke 冒烟测试(注册期 gin 静态/参数
  冲突即 panic + 关键 /api 路由断言)
- go build/vet/test ./... 全绿
This commit is contained in:
2026-08-27 19:24:43 +08:00
parent 5afc7fa9be
commit b1e9d9cae6
10 files changed
+376 -121

No files matched your search

+42
View File
@@ -0,0 +1,42 @@
# API 化改造 Todo
操作接口改为 `/api/` 前缀的 JSON APIPOST/PUT/DELETE、码+文案错误响应),页面路由保持不变。
## 基建(high
- [x] 1. 新建 `handlers/api.go``APIError(c, status, trKey)``APIOK(c, redirect, data)`、JSON 绑定/解析 helper
- [x] 2. `middleware/auth.go``AuthRequired`/`AdminRequired``/api` 路径前缀分支 401/403 JSON(非 API 保持 302
- [x] 3. `main.go`:注册 `/api` 分组(auth/article/admin/profile/my 子组)+ gin 静态/参数路由冲突冒烟测试(新增 `TestRegisterRoutesSmoke`,含附件端点搬移,`LoginRateLimiter` 导出)
- [x] 4. `templates/layouts/base.html`:增加 `blogAPI`/`blogForm`/`blogShowError` 共享 fetch 助手(CSRF 头、`e.submitter` 状态按钮、bool 复选框转换)
## 零行为搬移(medium
- [ ] 5. 附件三件套(admin/my+ `/api/profile/avatar` 换注册路径
- [ ] 6. 搬移端点模板更新:`article_create.html` 3 处 fetch URL、`profile.html` 1 处
## 功能改造(medium
- [ ] 7. 认证 API`auth.go` Login/Register/Logout JSON 化(429 限流、会话轮换保留)
- [ ] 8. 认证模板:`login.html`/`register.html` 改 fetch + 错误 div `id`base.html logout 改 fetch
- [ ] 9. 评论 API`comment.go` PostComment JSON 化(校验码复用 i18n 键)
- [ ] 10. 评论 API`admin_comment.go` approve/reject/delete JSON 化
- [ ] 11. 评论模板:`article.html` 评论表单 fetch、`comment_list.html` 操作后 reload
- [ ] 12. 文章 CRUD API`article.go`/`my_articles.go` 去 renderForm/Redirect 改 JSON(表单字段加 json tag
- [ ] 13. 文章模板:`article_create.html`/`my_article_form.html`/`article_list.html`/`my_articles.html` 改 fetch`easyMDE.value()``e.submitter`
- [ ] 14. 用户 API`admin_user.go` UserCreate/Update/Delete JSON 化(自防/最后管理员拦截改 403)
- [ ] 15. 用户模板:`user_form.html`/`user_list.html` 改 fetch
- [ ] 16. 设置 API`settings.go` 5 组 save JSON 化;site favicon 拆出 `POST /api/admin/settings/site/favicon`
- [ ] 17. 设置模板:`settings_site`/`settings_navlinks`/`settings_upload`/`settings_download`/`settings_comment` 5 页改 fetch
- [ ] 18. 个人资料 API`profile.go` UpdateProfile JSON 化(头像走 `/api/profile/avatar`
- [ ] 19. 个人资料模板:`profile.html` 文本表单改 fetch
## 测试与收尾(high
- [ ] 20. 新增 `handlers/api_test.go`happy path / 校验码 / 401 / 403 / CSRF 头 / 429 / 409
- [ ] 21. 更新 `security_test.go`/`p2_validation_test.go`/`p3_upload_test.go`/`session_upload_security_test.go` 到新 URL 与 JSON 断言
- [ ] 22. `go build ./... && go vet ./... && go test ./...` 全绿;README 路由表同步
## 执行说明
- 每步只改路由/响应层,不动解析校验逻辑(JSON binding 替换 PostForm 读取),单步可编译可测
- 并发状态:单一编辑者(本会话从第 1 项开始逐步执行)