cdn download support on shards + clean up #17
@@ -34,12 +34,14 @@ public class ServerFilesController : ControllerBase
|
||||
private readonly LightlessMetrics _metricsClient;
|
||||
private readonly MainServerShardRegistrationService _shardRegistrationService;
|
||||
private readonly CDNDownloadUrlService _cdnDownloadUrlService;
|
||||
private readonly CDNDownloadsService _cdnDownloadsService;
|
||||
|
||||
public ServerFilesController(ILogger<ServerFilesController> logger, CachedFileProvider cachedFileProvider,
|
||||
IConfigurationService<StaticFilesServerConfiguration> configuration,
|
||||
IHubContext<LightlessHub> hubContext,
|
||||
IDbContextFactory<LightlessDbContext> lightlessDbContext, LightlessMetrics metricsClient,
|
||||
MainServerShardRegistrationService shardRegistrationService, CDNDownloadUrlService cdnDownloadUrlService) : base(logger)
|
||||
MainServerShardRegistrationService shardRegistrationService, CDNDownloadUrlService cdnDownloadUrlService,
|
||||
CDNDownloadsService cdnDownloadsService) : base(logger)
|
||||
{
|
||||
_basePath = configuration.GetValueOrDefault(nameof(StaticFilesServerConfiguration.UseColdStorage), false)
|
||||
? configuration.GetValue<string>(nameof(StaticFilesServerConfiguration.ColdStorageDirectory))
|
||||
@@ -51,6 +53,7 @@ public class ServerFilesController : ControllerBase
|
||||
_metricsClient = metricsClient;
|
||||
_shardRegistrationService = shardRegistrationService;
|
||||
_cdnDownloadUrlService = cdnDownloadUrlService;
|
||||
_cdnDownloadsService = cdnDownloadsService;
|
||||
}
|
||||
|
||||
[HttpPost(LightlessFiles.ServerFiles_DeleteAll)]
|
||||
@@ -145,24 +148,16 @@ public class ServerFilesController : ControllerBase
|
||||
[AllowAnonymous]
|
||||
public async Task<IActionResult> DownloadFileDirect(string hash, [FromQuery] long expires, [FromQuery] string signature)
|
||||
{
|
||||
if (!_cdnDownloadUrlService.DirectDownloadsEnabled)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
var result = await _cdnDownloadsService.GetDownloadAsync(hash, expires, signature).ConfigureAwait(false);
|
||||
|
||||
hash = hash.ToUpperInvariant();
|
||||
if (!_cdnDownloadUrlService.TryValidateSignature(hash, expires, signature))
|
||||
return result.Status switch
|
||||
{
|
||||
return Unauthorized();
|
||||
}
|
||||
|
||||
var fileInfo = await _cachedFileProvider.DownloadAndGetLocalFileInfo(hash).ConfigureAwait(false);
|
||||
if (fileInfo == null)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
return PhysicalFile(fileInfo.FullName, "application/octet-stream");
|
||||
CDNDownloadsService.ResultStatus.Disabled => NotFound(),
|
||||
CDNDownloadsService.ResultStatus.Unauthorized => Unauthorized(),
|
||||
CDNDownloadsService.ResultStatus.NotFound => NotFound(),
|
||||
CDNDownloadsService.ResultStatus.Success => PhysicalFile(result.File!.FullName, "application/octet-stream"),
|
||||
_ => NotFound()
|
||||
};
|
||||
}
|
||||
|
||||
[HttpPost(LightlessFiles.ServerFiles_FilesSend)]
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
using LightlessSync.API.Routes;
|
||||
using LightlessSyncStaticFilesServer.Services;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace LightlessSyncStaticFilesServer.Controllers;
|
||||
|
||||
[Route(LightlessFiles.ServerFiles)]
|
||||
public class ShardServerFilesController : ControllerBase
|
||||
{
|
||||
private readonly CDNDownloadsService _cdnDownloadsService;
|
||||
|
||||
public ShardServerFilesController(ILogger<ShardServerFilesController> logger,
|
||||
CDNDownloadsService cdnDownloadsService) : base(logger)
|
||||
{
|
||||
_cdnDownloadsService = cdnDownloadsService;
|
||||
}
|
||||
|
||||
[HttpGet(LightlessFiles.ServerFiles_DirectDownload + "/{hash}")]
|
||||
[AllowAnonymous]
|
||||
public async Task<IActionResult> DownloadFileDirect(string hash, [FromQuery] long expires, [FromQuery] string signature)
|
||||
{
|
||||
var result = await _cdnDownloadsService.GetDownloadAsync(hash, expires, signature).ConfigureAwait(false);
|
||||
|
||||
return result.Status switch
|
||||
{
|
||||
CDNDownloadsService.ResultStatus.Disabled => NotFound(),
|
||||
CDNDownloadsService.ResultStatus.Unauthorized => Unauthorized(),
|
||||
CDNDownloadsService.ResultStatus.NotFound => NotFound(),
|
||||
CDNDownloadsService.ResultStatus.Success => PhysicalFile(result.File!.FullName, "application/octet-stream"),
|
||||
_ => NotFound()
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace LightlessSyncStaticFilesServer.Services;
|
||||
|
||||
public class CDNDownloadsService
|
||||
{
|
||||
public enum ResultStatus
|
||||
{
|
||||
Disabled,
|
||||
Unauthorized,
|
||||
NotFound,
|
||||
Success
|
||||
}
|
||||
|
||||
public readonly record struct Result(ResultStatus Status, FileInfo? File);
|
||||
|
||||
private readonly CDNDownloadUrlService _cdnDownloadUrlService;
|
||||
private readonly CachedFileProvider _cachedFileProvider;
|
||||
|
||||
public CDNDownloadsService(CDNDownloadUrlService cdnDownloadUrlService, CachedFileProvider cachedFileProvider)
|
||||
{
|
||||
_cdnDownloadUrlService = cdnDownloadUrlService;
|
||||
_cachedFileProvider = cachedFileProvider;
|
||||
}
|
||||
|
||||
public bool DownloadsEnabled => _cdnDownloadUrlService.DirectDownloadsEnabled;
|
||||
|
||||
public async Task<Result> GetDownloadAsync(string hash, long expiresUnixSeconds, string signature)
|
||||
{
|
||||
if (!_cdnDownloadUrlService.DirectDownloadsEnabled)
|
||||
{
|
||||
return new Result(ResultStatus.Disabled, null);
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(signature) || string.IsNullOrEmpty(hash))
|
||||
{
|
||||
return new Result(ResultStatus.Unauthorized, null);
|
||||
}
|
||||
|
||||
hash = hash.ToUpperInvariant();
|
||||
|
||||
if (!_cdnDownloadUrlService.TryValidateSignature(hash, expiresUnixSeconds, signature))
|
||||
{
|
||||
return new Result(ResultStatus.Unauthorized, null);
|
||||
}
|
||||
|
||||
var fileInfo = await _cachedFileProvider.DownloadAndGetLocalFileInfo(hash).ConfigureAwait(false);
|
||||
if (fileInfo == null)
|
||||
{
|
||||
return new Result(ResultStatus.NotFound, null);
|
||||
}
|
||||
|
||||
return new Result(ResultStatus.Success, fileInfo);
|
||||
}
|
||||
}
|
||||
@@ -88,6 +88,7 @@ public class Startup
|
||||
services.AddSingleton<ServerTokenGenerator>();
|
||||
services.AddSingleton<RequestQueueService>();
|
||||
services.AddSingleton<CDNDownloadUrlService>();
|
||||
services.AddSingleton<CDNDownloadsService>();
|
||||
services.AddHostedService(p => p.GetService<RequestQueueService>());
|
||||
services.AddHostedService(m => m.GetService<FileStatisticsService>());
|
||||
services.AddSingleton<IConfigurationService<LightlessConfigurationBase>, LightlessConfigurationServiceClient<LightlessConfigurationBase>>();
|
||||
@@ -205,7 +206,8 @@ public class Startup
|
||||
}
|
||||
else if (_isDistributionNode)
|
||||
{
|
||||
a.FeatureProviders.Add(new AllowedControllersFeatureProvider(typeof(CacheController), typeof(RequestController), typeof(DistributionController), typeof(SpeedTestController)));
|
||||
a.FeatureProviders.Add(new AllowedControllersFeatureProvider(typeof(CacheController), typeof(RequestController),
|
||||
typeof(DistributionController), typeof(ShardServerFilesController), typeof(SpeedTestController)));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user