YD_Event.Admin/YD_Event.Web.Entry/Controllers/CompetitionPublicController.cs
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

60 lines
2.3 KiB
C#

using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
namespace YD_Event.Web.Entry.Controllers;
/// <summary>
/// 官网赛事公开数据。只转发赛事服务的已发布状态,不提供草稿或写入接口。
/// </summary>
[ApiController]
[AllowAnonymous]
[Route("api/competition")]
public sealed class CompetitionPublicController : ControllerBase
{
private readonly IConfiguration _configuration;
private readonly IHttpClientFactory _httpClientFactory;
public CompetitionPublicController(IConfiguration configuration, IHttpClientFactory httpClientFactory)
{
_configuration = configuration;
_httpClientFactory = httpClientFactory;
}
[HttpGet("state")]
public async Task<IActionResult> GetState()
{
var adminUrl = _configuration["CompetitionApi:AdminUrl"]
?? "http://127.0.0.1:8787/api/competition/admin";
if (!Uri.TryCreate(adminUrl, UriKind.Absolute, out var adminTarget)
|| (adminTarget.Scheme != Uri.UriSchemeHttp && adminTarget.Scheme != Uri.UriSchemeHttps)
|| adminTarget.AbsolutePath != "/api/competition/admin"
|| !string.IsNullOrEmpty(adminTarget.Query))
return StatusCode(503, new { error = "官网赛事接口地址无效" });
var target = new Uri(adminTarget, "state");
Response.Headers["Cache-Control"] = "no-store";
try
{
var client = _httpClientFactory.CreateClient("WebsiteCompetition");
client.Timeout = TimeSpan.FromSeconds(15);
using var upstreamResponse = await client.GetAsync(target, HttpContext.RequestAborted);
var response = await upstreamResponse.Content.ReadAsStringAsync(HttpContext.RequestAborted);
return new ContentResult
{
Content = response,
ContentType = "application/json; charset=utf-8",
StatusCode = (int)upstreamResponse.StatusCode
};
}
catch (HttpRequestException)
{
return StatusCode(502, new { error = "官网赛事接口连接失败" });
}
catch (TaskCanceledException) when (!HttpContext.RequestAborted.IsCancellationRequested)
{
return StatusCode(504, new { error = "官网赛事接口响应超时" });
}
}
}