04 · HTTP API 合约
读者:机器客户端 / 集成方;浏览器 UI 不使用本文件作为主路径
前置:03-data-model.md、08-gitea-ssr-architecture.md
源码:routers/setup.go、modules/auth/auth.go
本分支(rebuild/gitea-ssr)浏览器走 routers/web 模板 + 表单。
下列 JSON 合约保留作历史对照与未来机器 API;当前进程仅注册 health / OIDC / robots / sitemap / media 等机器相关路由,论坛 CRUD 的 /api/* 已从路由表移除(handler 源码可删可留,不以 SPA 兼容为目的)。
main 分支 SPA 仍完整实现下表;对照请 checkout main。
1. 本分支已注册的机器入口
| 方法 |
路径 |
说明 |
| GET |
/health |
探活 |
| GET |
/robots.txt |
抓取规则 |
| GET |
/sitemap.xml |
站点地图 |
| GET/POST |
/oauth/*、/.well-known/openid-configuration |
OIDC Provider |
| GET |
/media/thumb/*、/uploads/* |
媒体 |
2. 历史 JSON 合约(main / 对照,本分支默认不挂载)
以下章节描述原 SPA 使用的 /api 形状,便于迁移业务语义;实现 UI 时请用 web 表单,勿恢复双轨。
通用约定(历史)
| 项 |
约定 |
| Base |
同源;credentials: 'same-origin' |
| 成功 |
HTTP 2xx + JSON body |
| 失败 |
非 2xx + { "error": "..." } |
| 鉴权 |
Cookie jiang13_session(opaque);机器 OIDC 用 Bearer |
分页形态差异
| 场景 |
典型字段 |
| 前台帖列表 |
posts, total, page, size, has_more |
| 后台多数列表 |
total, page, total_pages + 实体数组 |
| 私信会话消息 |
before 游标式 |
3. 基础设施 / SEO / 静态(节选,仍有效)
| 方法 |
路径 |
鉴权 |
说明 |
| GET |
/health |
无 |
{ "status": "ok" } |
| GET |
/robots.txt |
无 |
文本 |
| GET |
/sitemap.xml |
无 |
XML |
| GET |
/media/thumb/*filepath |
无 |
缩略图 / WebP 等 |
| GET |
/uploads/* |
无 |
静态上传文件 |
3. OIDC Provider
| 方法 |
路径 |
鉴权 |
说明 |
| GET |
/.well-known/openid-configuration |
无 |
Discovery |
| GET |
/oauth/jwks |
无 |
JWKS |
| GET |
/oauth/authorize |
OptionalAuth |
授权码流程 |
| POST |
/oauth/token |
无(客户端凭证) |
换 token |
| GET/POST |
/oauth/userinfo |
Bearer |
用户信息 |
| GET/POST |
/oauth/logout |
视实现 |
登出 |
细节以 service/oidc.go / handler/oidc.go 为准。
4. 公开 API(/api + OptionalAuth)
4.1 会话与站点
| 方法 |
路径 |
响应要点 |
| GET |
/api/me |
{ user: UserSelf | null } |
| GET |
/api/stats |
{ users, posts, boards, comments } |
| GET |
/api/forum-limits |
ForumLimitsPublic(无限流内部字段) |
| GET |
/api/site-branding |
SiteBranding(可含 site_url) |
| GET |
/api/captcha |
{ id, image } image 为 data URL 或 base64 |
| GET |
/api/register/config |
见下 |
RegisterConfig
4.2 认证(限流)
| 方法 |
路径 |
Body |
响应 |
| POST |
/api/register |
Form/JSON: username, password, nickname, email, captcha_id, captcha, email_code? |
成功后通常种 cookie |
| POST |
/api/login |
Form: username, password |
种 cookie |
| POST |
/api/register/email-code |
JSON { email } |
{ message } |
| POST |
/api/password-reset/email-code |
JSON { email } |
{ message } |
| POST |
/api/password-reset |
JSON { email, email_code, new_password } |
{ message } |
4.3 内容只读
| 方法 |
路径 |
Query / 说明 |
| GET |
/api/boards |
{ boards: Board[] } |
| GET |
/api/posts |
见下表 |
| GET |
/api/posts/hot |
热门列表 |
| GET |
/api/posts/:id |
skip_view=1 可选;返回 PostDetailResponse |
| GET |
/api/posts/:id/comments |
my_ids 可选(逗号分隔,便于标自己的楼) |
| GET |
/api/tags |
limit 默认 40 → { tags: [{name,count}] } |
| GET |
/api/comments/recent |
{ comments: RecentComment[] } |
| GET |
/api/users/search |
q, limit |
| GET |
/api/users/recent |
{ users: RecentUser[] } |
| GET |
/api/users/:id |
{ user: UserPublic, stats } |
| GET |
/api/pages |
已发布摘要列表 |
| GET |
/api/pages/:slug |
单页详情 |
| GET |
/api/projects |
page, limit, q |
GET /api/posts Query
| 参数 |
说明 |
| page |
默认 1 |
| size |
默认 page_size_default,上限 100 |
| board_id |
0 或不传=全部 |
| user_id |
某用户的帖 |
| keyword |
搜索词 |
| tag |
标签 |
| author |
用户名优先,否则昵称精确匹配 |
| title_only |
1/true 仅搜标题 |
| sort |
latest | reply | hot |
响应示例
PostDetailResponse 要点
4.4 游客可写评论
| 方法 |
路径 |
限流 |
Body |
| POST |
/api/posts/:id/comments |
comment |
Form: content, reply_to?, is_private?, 以及游客字段(以实现为准) |
登录用户发评也走此路径(RequireAuth 组外公开组已注册该路由)。
5. 需登录 API(/api + RequireAuth)
5.1 会话与资料
| 方法 |
路径 |
Body |
响应 |
| POST |
/api/logout |
|
清 cookie |
| GET |
/api/favorites |
|
{ favorites, total } |
| GET |
/api/profile/stats |
|
{ stats: UserActivityStats } |
| POST |
/api/profile/nickname |
Form nickname |
|
| POST |
/api/profile/signature |
Form signature |
{ message, user } |
| POST |
/api/profile/password |
Form old_password, new_password |
|
| POST |
/api/profile/avatar |
Form avatar=file |
{ avatar } |
| POST |
/api/uploads/image |
Form image=file |
{ url } |
5.2 帖子写操作
| 方法 |
路径 |
Body |
响应 |
| POST |
/api/posts |
Form: board_id, title, content, tags?, post_type?, poll_options?, bounty_points?, lottery_winner_count? |
{ message, post_id, status } |
| PUT |
/api/posts/:id |
Form: title, content, tags?, board_id?, post_type? |
{ message } |
| DELETE |
/api/posts/:id |
|
软删 |
| GET |
/api/posts/:id/revisions |
|
{ revisions } |
| GET |
/api/posts/:id/revisions/:revId |
|
{ revision } |
| POST |
/api/posts/:id/like |
|
{ liked, like_count } |
| POST |
/api/posts/:id/favorite |
|
{ favorited } |
| POST |
/api/posts/:id/resolve |
Form resolved=1|0 |
{ question_resolved } |
| POST |
/api/posts/:id/poll/vote |
JSON { option_ids: number[] } |
{ poll } |
| POST |
/api/posts/:id/poll/close |
|
{ poll } |
| POST |
/api/posts/:id/bounty/award |
Form comment_id |
|
| POST |
/api/posts/:id/bounty/refund |
|
|
| POST |
/api/posts/:id/lottery/draw |
|
{ lottery } |
| POST |
/api/posts/:id/report |
JSON { reason, detail? } |
{ report } |
| POST |
/api/posts/:id/unlock |
JSON { block_key } |
见下 |
poll_options JSON 示例(Form 字段字符串)
unlock 响应
5.3 评论写操作
| 方法 |
路径 |
Body |
| POST |
/api/comments/:id/like |
→ { liked, like_count } |
| POST |
/api/comments/:id/report |
JSON { reason, detail? } |
| PUT |
/api/comments/:id |
Form content |
| DELETE |
/api/comments/:id |
|
5.4 私信
| 方法 |
路径 |
说明 |
| GET |
/api/messages/unread-count |
{ count, dm_count?, notify_count? } |
| GET |
/api/messages/notifications |
page, size, kind |
| POST |
/api/messages/notifications/read |
|
| GET |
/api/messages/conversations |
page, size |
| GET |
/api/messages/conversations/:peerId |
size, before;peerId=0 为系统 |
| POST |
/api/messages/conversations/:peerId/read |
|
| POST |
/api/messages |
JSON { to_user_id, subject?, content } |
| POST |
/api/messages/read-all |
|
5.5 经济
| 方法 |
路径 |
说明 |
| GET |
/api/me/points |
page;含 ledger、check_in、lottery |
| GET/POST |
/api/me/check-in |
状态 / 执行签到 |
| GET/POST |
/api/me/lottery |
状态 / 抽奖 |
5.6 友链申请
| 方法 |
路径 |
Body |
| POST |
/api/friend-links/apply |
JSON name, url, logo, link_on_homepage, reciprocal_page_url? |
| POST |
/api/friend-links/logo |
Form logo=file → { url } |
| GET |
/api/friend-links/my-applies |
|
| PUT |
/api/friend-links/applies/:id |
同申请字段 |
| DELETE |
/api/friend-links/applies/:id |
取消 |
6. 管理 API(/api/admin + Auth + Admin)
6.1 仪表盘与设置
| 方法 |
路径 |
说明 |
| GET |
/dashboard |
AdminDashboard |
| GET |
/settings |
AdminSettings 聚合 |
| PUT |
/settings/forum |
ForumLimits |
| PUT |
/settings/mail |
MailConfig |
| POST |
/settings/mail/test |
{ to } |
| PUT |
/settings/oidc |
OIDCConfig |
| PUT |
/settings/gitea |
后置(501) |
| POST |
/settings/gitea/sync |
后置(501) |
| PUT |
/settings/storage |
StorageConfig |
| PUT |
/settings/branding |
SiteBranding |
| POST |
/settings/branding/upload |
Form kind=logo|favicon|og_image, file |
| POST |
/settings/branding/clear |
JSON { kind } |
| GET/PUT |
/settings/filter-words |
GET 读;PUT { content } |
(上表路径均相对于 /api/admin。)
6.2 OAuth 客户端
| 方法 |
路径 |
| GET/POST |
/oauth/clients |
| PUT/DELETE |
/oauth/clients/:id |
创建/更新 body:name, redirect_uris, client_id?, enabled?, client_secret?, rotate_secret?。
6.3 板块 / 单页 / 友链
| 方法 |
路径 |
| POST/PUT/DELETE |
/boards, /boards/:id |
| GET/POST |
/pages |
| GET/PUT/DELETE |
/pages/:id |
| PUT |
/pages/:id/published → { published } |
| GET |
/friend-link-applies |
| PUT |
/friend-link-settings |
| POST |
/friend-link-applies/:id/approve | reject | recheck |
6.4 帖子审核与运营
| 方法 |
路径 |
Body |
| GET |
/posts |
page, keyword, status |
| GET |
/posts/trash |
|
| POST |
/posts/:id/pin |
{ pinned } |
| POST |
/posts/:id/board-pin |
{ board_pinned } |
| POST |
/posts/:id/feature |
{ featured } |
| POST |
/posts/:id/lock |
{ locked } → edit_locked |
| POST |
/posts/:id/comments-lock |
{ locked } |
| POST |
/posts/:id/approve |
|
| POST |
/posts/:id/reject |
{ reason } |
| POST |
/posts/:id/restore |
|
| DELETE |
/posts/:id/purge |
硬删 |
| DELETE |
/posts/:id |
软删 |
6.5 评论 / 举报 / 用户 / 徽章 / 媒体 / 备份
| 方法 |
路径 |
说明 |
| GET |
/comments, /comments/trash |
|
| GET |
/comments/:id/revisions |
|
| POST |
/comments/:id/approve | reject | restore |
reject 可带 reason |
| DELETE |
/comments/:id, /comments/:id/purge |
|
| GET |
/reports |
page, status |
| POST |
/reports/:id/handle |
{ action, handle_note?, reject_reason? };action=dismiss|resolve|reject_post|reject_comment |
| GET |
/users |
page, keyword, filter |
| POST |
/users/:id/ban |
{ banned } |
| POST |
/users/:id/verify |
{ verified } |
| POST |
/users/:id/level |
{ level } |
| POST |
/users/:id/points |
{ delta, note? } |
| POST |
/users/:id/badges |
{ badge_id, revoke? } |
| GET/POST |
/badges |
列表 / upsert |
| GET |
/media |
category, page, size, q |
| POST |
/media/delete |
{ urls: string[] } |
| POST |
/backup |
{ filename, download } |
| GET |
/backup/download/:name |
文件下载 |
7. 核心类型速查(与前端对齐)
详见 [frontend/src/api/types.ts]((仅 main)frontend/src/api/types.ts)。实现时至少对齐:
User / UserPublic / UserActivityStats
Board / PostItem / PostDetailResponse / Comment
ForumLimits / ForumLimitsPublic / SiteBranding
PollView / PostLotteryView
PrivateMessage / MessageConversation
PostReport / FriendLinkApply / BadgeDef / PointLedger
CheckInStatus / LotteryStatus
AdminDashboard / AdminSettings / StorageConfig / MailConfig / OIDCConfig
8. 鉴权错误语义(现网)
中间件对未登录 / 过期 / 禁言返回 JSON error(并可能清 cookie)。前端统一 throw new Error(data.error)。新站应保持可区分的错误文案或错误码,避免前端无法提示。
源:middleware/auth.go。