From e0f1bdfc58393090f3ba99f5d5903d2955a01efa Mon Sep 17 00:00:00 2001 From: Julien Date: Tue, 27 Aug 2024 20:45:11 +0200 Subject: [PATCH] S2C proxy --- .../Controllers/S2CController.cs | 83 +++++++++++++++++++ ArmaRealMapWebSite/Startup.cs | 6 ++ 2 files changed, 89 insertions(+) create mode 100644 ArmaRealMapWebSite/Controllers/S2CController.cs diff --git a/ArmaRealMapWebSite/Controllers/S2CController.cs b/ArmaRealMapWebSite/Controllers/S2CController.cs new file mode 100644 index 00000000..58dd2ec6 --- /dev/null +++ b/ArmaRealMapWebSite/Controllers/S2CController.cs @@ -0,0 +1,83 @@ +using System; +using System.IO; +using System.Net.Http; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Logging; +using SixLabors.ImageSharp; + +namespace ArmaRealMapWebSite.Controllers +{ + public class S2CController : Controller + { + private readonly string cacheLocation = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "GameRealisticMap", "S2CloudlessCache"); + private readonly SemaphoreSlim downloadSemaphore = new SemaphoreSlim(1, 1); + + private readonly HttpClient httpClient; + private readonly ILogger logger; + + public S2CController(IHttpClientFactory httpClientFactory, ILogger logger) + { + this.httpClient = httpClientFactory.CreateClient("S2C"); + this.logger = logger; + } + + [Route("sat/{dataset}/{zoom}/{y}/{x}.jpg")] + public async Task GetTile(string dataset, int zoom, int y, int x) + { + if (dataset != "s2cloudless-2020" || zoom > 16 || zoom < 0 || x < 0 || y < 0) + { + return NotFound(); + } + var endPoint = "https://tiles.maps.eox.at/wmts/1.0.0/s2cloudless-2020_3857/default/GoogleMapsCompatible/"; + var filePath = FormattableString.Invariant($"{zoom}/{y}/{x}.jpg"); + var cacheFile = System.IO.Path.Combine(cacheLocation, filePath); + if (!System.IO.File.Exists(cacheFile)) + { + await downloadSemaphore.WaitAsync().ConfigureAwait(false); + try + { + if (!System.IO.File.Exists(cacheFile)) + { + Directory.CreateDirectory(Path.GetDirectoryName(cacheFile)); + var bytes = await Load(new Uri(endPoint + filePath, UriKind.Absolute)).ConfigureAwait(false); + var id = Image.DetectFormat(bytes); + if (id.DefaultMimeType == "image/jpeg") + { + await System.IO.File.WriteAllBytesAsync(cacheFile, bytes); + } + } + } + finally + { + downloadSemaphore.Release(); + } + } + if (!System.IO.File.Exists(cacheFile)) + { + return NotFound(); + } + return File(await System.IO.File.ReadAllBytesAsync(cacheFile), "image/jpeg"); + } + + private async Task Load(Uri uri) + { + int sleep = 10; + while (sleep < 5000) + { + await Task.Delay(sleep).ConfigureAwait(false); + try + { + return await httpClient.GetByteArrayAsync(uri).ConfigureAwait(false); + } + catch (Exception ex) + { + logger.Log(LogLevel.Warning, "{0}: {1}", uri.OriginalString, ex.Message); + } + sleep += 500; + } + throw new ApplicationException($"Failed to load '{uri}'"); + } + } +} diff --git a/ArmaRealMapWebSite/Startup.cs b/ArmaRealMapWebSite/Startup.cs index 200dae80..7ee544ef 100644 --- a/ArmaRealMapWebSite/Startup.cs +++ b/ArmaRealMapWebSite/Startup.cs @@ -53,6 +53,12 @@ public void ConfigureServices(IServiceCollection services) ); }); + services.AddHttpClient("S2C", c => { + + c.DefaultRequestHeaders.Add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/111.0"); + + }); + if (Environment.OSVersion.Platform == PlatformID.Unix) { services.AddDataProtection()