using System.Text;
using Microsoft.AspNetCore.Mvc;
using economy.Controllers.Price.Global;
namespace economy.Controllers
{
// sitemap.xml 생성
//
// 기존에는 wwwroot/sitemap.xml 정적 파일을 외부 생성기로 만들어 두었는데,
// 같은 페이지의 쿼리스트링 변형(페이지네이션 41개, 조회기간/코드 파라미터 등)이 대부분을 차지해
// 98건 중 실제 고유 페이지는 20여 개뿐이었고 lastmod 도 2025-08-10 에 고정되어 있었다.
// 여기서는 정규 URL 만 내보낸다.
public class SitemapController : Controller
{
// 리버스 프록시 뒤에서는 Request.Scheme 이 http 로 들어올 수 있어 설정값을 우선 사용한다.
private const string DefaultBaseUrl = "https://economy.web.or.kr";
// 파라미터가 없는 정규 경로만 담는다.
// 제외 대상:
// - Business/Search, Whois/Search : [HttpPost] 전용이라 GET 은 405
// - Home/Error : 오류 페이지
// - Price/Domestic/Item/Detail/{item} : 품목 코드가 외부 API 응답에서 오므로 목록을 고정할 수 없다.
// Item/List 페이지의 링크를 통해 크롤링된다.
private static readonly string[] StaticPaths =
{
"/",
"/Home/Privacy",
"/Business/Number",
"/Days/Anniversary",
"/Days/Holiday",
"/Days/Seasonal",
"/Days/Sundry",
"/FIFA",
"/Financial/Exchange",
"/Financial/Interest",
"/Financial/International",
"/Lotto",
"/Whois",
"/Price/Domestic/Emission",
"/Price/Domestic/Flower",
"/Price/Domestic/Gold",
"/Price/Domestic/Oil",
"/Price/Domestic/Item/List.cshtml",
"/Price/Global/NaturalGas"
};
private readonly IConfiguration _configuration;
public SitemapController(IConfiguration configuration)
{
_configuration = configuration;
}
[HttpGet("/sitemap.xml")]
[HttpHead("/sitemap.xml")]
[ResponseCache(Duration = 3600, Location = ResponseCacheLocation.Any)]
public IActionResult Index()
{
var baseUrl = (_configuration["Site:BaseUrl"] ?? DefaultBaseUrl).TrimEnd('/');
// 시세 페이지는 매일 갱신되므로 날짜 단위로만 표기한다.
var today = DateTime.UtcNow.ToString("yyyy-MM-dd");
var builder = new StringBuilder();
builder.AppendLine(@"");
builder.AppendLine(@"");
foreach (var path in StaticPaths)
{
AppendUrl(builder, baseUrl + path, today, "daily", path == "/" ? "1.0" : "0.8");
}
// 국제 원자재 시세. 품목 목록은 GlobalController.CommodityMap 을 그대로 읽어
// 라우트가 실제로 처리하는 값과 어긋나지 않게 한다.
foreach (var commodity in GlobalController.CommodityMap.Keys.OrderBy(key => key, StringComparer.OrdinalIgnoreCase))
{
AppendUrl(builder, $"{baseUrl}/Price/Global/{commodity}", today, "daily", "0.8");
}
builder.AppendLine("");
return Content(builder.ToString(), "application/xml", Encoding.UTF8);
}
private static void AppendUrl(StringBuilder builder, string location, string lastModified, string changeFrequency, string priority)
{
builder.AppendLine(" ");
builder.AppendLine($" {location}");
builder.AppendLine($" {lastModified}");
builder.AppendLine($" {changeFrequency}");
builder.AppendLine($" {priority}");
builder.AppendLine(" ");
}
}
}