using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; namespace YD_Event.Web.Entry.Controllers; /// /// 官网赛事公开数据。只转发赛事服务的已发布状态,不提供草稿或写入接口。 /// [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 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 = "官网赛事接口响应超时" }); } } }