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.
60 lines
2.3 KiB
C#
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 = "官网赛事接口响应超时" });
|
|
}
|
|
}
|
|
}
|