using System.Net.Http.Headers;
using Microsoft.Extensions.Logging;
namespace Infrastructure.StockData;
///
/// OpenDART(opendart.fss.or.kr) 호출 공통 — 인증은 URL query param crtfc_key (헤더 아님, KRX 와 다름).
/// 호출부가 crtfc_key 를 붙인 완성 URL 을 넘기며, 여기선 Accept json + 간단 3회 재시도(2s/4s 백오프)만 담당.
///
internal static class OpenDartHttp
{
public const string ClientName = "OpenDart";
private const int MaxAttempts = 3;
public static async Task GetStringWithRetryAsync(HttpClient client, string url, ILogger logger, CancellationToken ct)
{
for (var attempt = 1; ; attempt++)
{
try
{
using var request = new HttpRequestMessage(HttpMethod.Get, url);
request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
// OpenDART 는 User-Agent 없는 요청을 302 → /error1.html 로 튕긴다(봇 차단). UA 필수.
request.Headers.UserAgent.ParseAdd("antooza/1.0 (+https://antooza.com)");
using var response = await client.SendAsync(request, ct);
response.EnsureSuccessStatusCode();
return await response.Content.ReadAsStringAsync(ct);
}
catch (Exception ex) when (ex is not OperationCanceledException && attempt < MaxAttempts)
{
logger.LogWarning(ex, "[OpenDart] HTTP 실패 — 재시도 {Attempt}/{Max}", attempt, MaxAttempts);
await Task.Delay(TimeSpan.FromSeconds(2 * attempt), ct);
}
}
}
}