YD_Event.Admin/WEBSITE-COMPETITION-BACKEND.md
ltx 2e00719d56 feat(website): expose published competition state
Add an anonymous read-only state endpoint for the public website, backed by the private competition service. Keep draft reads and writes behind existing admin login and document the production routing.
2026-10-20 09:15:33 +08:00

5.4 KiB
Raw Blame History

官网赛事信息后端接口

功能与调用链

YD_Event.Web 的“官网赛事信息”页面请求当前环境的 GET/PUT /api/website-competition。此接口由 YD_Event.Admin 提供,沿用后台登录认证;管理页不需要填写接口地址或管理密钥。

正式环境访问基地址为 https://jitsi-web.yuedongsports.com/,管理接口完整地址为 https://jitsi-web.yuedongsports.com/api/website-competition。此地址是后台对外入口;CompetitionApi:AdminUrl 是后端转发到官网赛事服务的地址,需单独配置。

YD_Event.Admin 在服务端把请求转发到官网赛事服务的内部 /api/competition/admin。两台服务器通过私网连接,不使用服务间管理密钥。官网赛事服务按来源 IP 放行内部管理请求,持久化草稿或发布状态,供公开页面读取。本仓库不新增赛事数据库表。

官网公开页面不访问需要登录的管理接口,而是匿名请求 GET /api/competition/state。此路由由 CompetitionPublicController 通过同一私网赛事服务读取 /api/competition/state;赛事服务在未发布时只返回空态。公开接口只支持读取,不提供草稿或写入能力。官网每 10 秒重新读取一次。

YD_Event.Web 管理页
  → 当前域名 /api/website-competition(后台登录态)
  → YD_Event.Admin(通过私网转发)
  → 官网赛事服务 /api/competition/admin(来源 IP 白名单)
  → 持久化赛事 JSON / 官网公开接口

接口

方法 路径 说明
GET /api/website-competition 读取当前环境的完整赛事草稿,包括未发布内容
PUT /api/website-competition 保存赛事信息及 published 状态,JSON 请求体上限为 8 MB
GET /api/competition/state 匿名读取已发布数据;未发布时返回空态

前两个管理方法要求已有的后台登录态;公开方法不要求登录。控制器原样转发上游的 JSON 响应和 HTTP 状态码。数据的主要结构如下;详细字段由管理页 Excel 模板及官网赛事服务校验规则约束。

{
  "published": false,
  "competition": { "nameZh": "", "nameEn": "", "dateZh": "", "dateEn": "", "venueZh": "", "venueEn": "" },
  "notice": { "enabled": false, "textZh": "", "textEn": "" },
  "schedule": { "currentId": "", "callingId": "", "upcomingCount": 3, "items": [] },
  "results": { "overall": [], "challenge": [], "battle": [] },
  "players": [],
  "records": []
}

服务端配置

配置键 环境变量写法 说明
CompetitionApi:AdminUrl CompetitionApi__AdminUrl 官网赛事服务内部管理接口完整 URL;本地默认 http://127.0.0.1:8787/api/competition/admin

正式环境两台服务器分机部署,必须将 CompetitionApi__AdminUrl 配置为 http://<赛事服务私网 IP>:8787/api/competition/admin,不能使用默认的 127.0.0.1。赛事服务应只在私网地址监听,并通过 COMPETITION_ADMIN_ALLOWED_IPS 放行 YD_Event.Admin 的私网 IP;防火墙只允许后台服务器连接该端口。公网 Nginx 必须屏蔽 /api/competition/admin,避免绕过后台登录认证直接修改赛事数据。

公开状态接口从 CompetitionApi__AdminUrl 推导同源的 /api/competition/state,因此不需要额外的地址或密钥配置。正式环境沿用现有 /api/ 反向代理到 YD_Event.Admin;不要把公开接口直接转发到赛事服务。

部署步骤

  1. 启动官网赛事服务,设置持久化数据路径、私网监听地址、后台服务器的来源 IP 白名单;其健康检查为 GET /api/competition/ping。
  2. 在 YD_Event.Admin 的运行环境配置内网管理接口 URL,然后启动或重启后端。Startup 已注册专用 WebsiteCompetition HttpClient。
  3. 将后台站点同源的 /api/website-competition 路由转发到 YD_Event.Admin。不要把该路径直接暴露或转发到官网赛事服务管理接口。
  4. 管理员登录 YD_Event.Web 后打开“官网赛事信息”,导入 .xlsx、核对草稿并保存;需要公开展示时再开启“公开发布”。
  5. 从 https://www.yuedongsports.com 携带 Origin 请求正式环境的 GET /api/competition/state,确认返回已发布数据或空态,以及允许官网来源的 CORS 响应头。

错误排查

状态 常见原因
401/403 后台未登录或无权访问;若由上游返回 403,检查后台服务器私网 IP 是否在 COMPETITION_ADMIN_ALLOWED_IPS 中
413 PUT 请求体超过 8 MB
502 官网赛事服务无法连接
503 上游 URL 无效
504 官网赛事服务超过 30 秒未响应

保存时上游的字段校验错误会原样返回,管理页会展示错误信息。

验证

dotnet build .\YD_Event.Web.Entry\YD_Event.Web.Entry.csproj --no-restore

确认官网赛事服务的 /api/competition/ping 返回成功;使用已有后台登录态访问 GET /api/website-competition,应返回上述赛事结构。未经登录直接访问应被后台认证拒绝。PUT 应先在测试环境使用草稿数据验证,再按发布流程操作。

匿名访问 GET /api/competition/state 应返回公开空态或已发布数据。若返回 404,检查新控制器是否已部署,以及 Nginx 是否仍使用直接代理赛事服务的旧片段;若返回 502,检查私网连接及 CompetitionApi__AdminUrl。