Newer
Older
percord / extra / admin-api / Interop / Spacebar.Interop.Cdn.Abstractions / ProxyFileSource.cs
using System.Net;
using ArcaneLibs;
using ArcaneLibs.Extensions;
using ArcaneLibs.Extensions.Streams;

namespace Spacebar.Interop.Cdn.Abstractions;

/// <summary>
/// Class only exists as a stepping stone between old cdn and migrations...
/// </summary>
/// <param name="baseUrl"></param>
public class ProxyFileSource(string baseUrl) : IFileSource {
    private static LruFileCache _cache = new(100 * 1024 * 1024); // 100 MB

    private readonly StreamingHttpClient _httpClient = new() {
        BaseAddress = new Uri(baseUrl)
    };

    public string BaseUrl => baseUrl;

    public async Task<IFileSource> Init(CancellationToken? cancellationToken = null) {
        return this;
    }

    public async Task<FileInfo> GetFile(string path, CancellationToken? cancellationToken = null) {
        var res = await _cache.GetOrAdd(path, async () => {
            var res = await _httpClient.SendUnhandledAsync(new(HttpMethod.Get, path), cancellationToken);
            res.EnsureSuccessStatusCode();
            var ms = new MemoryStream();
            await res.Content.CopyToAsync(ms);
            return new LruFileCache.Entry {
                Data = ms.ToArray(),
                MimeType = res.Content.Headers.ContentType?.MediaType ?? "application/octet-stream"
            };
        });

        return new() {
            Stream = new MemoryStream(res.Data),
            MimeType = res.MimeType
        };
    }

    public async Task<bool> FileExists(string path, CancellationToken? cancellationToken = null) {
        var res = await _httpClient.SendUnhandledAsync(new(HttpMethod.Head, path), cancellationToken);
        if (!res.IsSuccessStatusCode) {
            await using var s = await res.Content.ReadAsStreamAsync();
            Console.WriteLine($"Got {res.StatusCode}: ({res.Content.Headers.ContentLength}b of {res.Content.Headers.ContentType})\n{s.ReadToEnd().AsString()}");
        }

        return res.IsSuccessStatusCode;
    }

    public async Task WriteFile(string path, Stream stream) {
        Console.WriteLine("Can't write to HTTP store! Ignoring.");
    }
}