using Microsoft.AspNetCore.Mvc; using AS1024.GeoFeed.Core.Interfaces; using Microsoft.Extensions.Caching.Memory; using AS1024.GeoFeed.Models; using System.Text; using AS1024.GeoFeed.Core.Tools; namespace AS1024.GeoFeed.Controllers { [ApiController] [Route("[controller]")] [Route("[controller].csv")] public class GeofeedController : ControllerBase { private readonly IGeoFeedProvider builder; private readonly IMemoryCache memoryCache; private readonly IWebHostEnvironment environment; private readonly ILogger logger; private readonly IGeoFeedPersistentCacheProvider geoFeedPersistentCache; private const string GeoFeedCacheKey = "GeoFeedData"; public GeofeedController(IGeoFeedProvider builder, IMemoryCache memoryCache, IWebHostEnvironment environment, ILogger logger, IGeoFeedPersistentCacheProvider geoFeedPersistentCache) { this.logger = logger; this.geoFeedPersistentCache = geoFeedPersistentCache; this.builder = builder; this.memoryCache = memoryCache; this.environment = environment; } [HttpGet] [Route("")] public async Task Get() { bool isCached = true; try { if (!memoryCache.TryGetValue(GeoFeedCacheKey, out List? feed)) { isCached = false; feed = await builder.GetGeoFeedData(); if (environment.IsProduction()) { MemoryCacheEntryOptions cacheEntryOptions = new MemoryCacheEntryOptions() .SetSlidingExpiration(TimeSpan.FromMinutes(15)); memoryCache.Set(GeoFeedCacheKey, feed, cacheEntryOptions); } } return ReturnFile(feed, isCached); } catch (HttpRequestException ex) { logger.LogWarning($"Temporary failure of retrieving GeoData from upstream. {ex}"); var cachedData = geoFeedPersistentCache.GetGeoFeed(); return ReturnFile(cachedData); } catch (Exception ex) { logger.LogError($"Geofeed generation failed. Exception: {ex}"); return StatusCode(500); } } [NonAction] private IActionResult ReturnFile(List? feed, bool isCached = false) { string csvContent = feed.ToGeoFeedCsv(true, isCached); // Assuming ToGeoFeedCsv() returns a string in CSV format. return ReturnFile(csvContent); } [NonAction] private IActionResult ReturnFile(string csvContent) { byte[] contentBytes = Encoding.UTF8.GetBytes(csvContent); string contentType = "text/csv"; return new FileContentResult(contentBytes, contentType) { FileDownloadName = "geofeed.csv" }; } } }