Файлы, правки отображения
This commit is contained in:
@@ -9,17 +9,43 @@ using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Routing;
|
||||
using Microsoft.Extensions.Caching.Memory;
|
||||
|
||||
namespace Knot.Host.Presentation.Endpoints;
|
||||
namespace Knot.Modules.Storage.Presentation.Endpoints;
|
||||
|
||||
public static class FilesEndpoints
|
||||
{
|
||||
public static void MapFilesEndpoints(this WebApplication app)
|
||||
{
|
||||
var group = app.MapGroup("api/files");
|
||||
|
||||
group.MapGet("{id}", async (string id, [FromQuery] bool download, [FromServices] IFileStorageService fileStorage, [FromServices] IMemoryCache cache, CancellationToken ct) =>
|
||||
// Federation remote endpoint - most specific, must be first
|
||||
app.MapGet("/api/files/remote/{domain}/{id}", async (string domain, string id, HttpClient httpClient, ISettingsService settingsService, CancellationToken ct) =>
|
||||
{
|
||||
var settings = await settingsService.GetSettingsAsync(ct);
|
||||
if (!settings.Federation.Enabled) return Results.Forbid();
|
||||
|
||||
var targetUrl = $"{domain.TrimEnd('/')}/api/federation/v1/proxy/{id}";
|
||||
|
||||
var request = new HttpRequestMessage(HttpMethod.Get, targetUrl);
|
||||
request.Headers.Add("X-Knot-Domain", settings.System.DomainUrl);
|
||||
|
||||
using (var rsa = RSA.Create())
|
||||
{
|
||||
rsa.ImportPkcs8PrivateKey(Convert.FromBase64String(settings.Federation.PrivateKey!), out _);
|
||||
var dataToSign = Encoding.UTF8.GetBytes(id + settings.System.DomainUrl);
|
||||
var signature = Convert.ToBase64String(rsa.SignData(dataToSign, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1));
|
||||
request.Headers.Add("X-Knot-Signature", signature);
|
||||
}
|
||||
|
||||
var response = await httpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, ct);
|
||||
if (!response.IsSuccessStatusCode) return Results.NotFound();
|
||||
|
||||
var remoteStream = await response.Content.ReadAsStreamAsync(ct);
|
||||
var contentType = response.Content.Headers.ContentType?.ToString() ?? "application/octet-stream";
|
||||
|
||||
return Results.Stream(remoteStream, contentType, enableRangeProcessing: true);
|
||||
});
|
||||
|
||||
// Main file download endpoint - without group prefix to avoid routing issues
|
||||
app.MapGet("/api/files/{id}", async ([FromRoute] string id, [FromServices] IFileStorageService fileStorage, [FromServices] IMemoryCache cache, HttpContext httpContext, [FromQuery] bool download = false, CancellationToken ct = default) =>
|
||||
{
|
||||
// (Текущая логика локальных файлов остается без изменений)
|
||||
try
|
||||
{
|
||||
var cacheKey = $"file_{id}";
|
||||
@@ -50,39 +76,9 @@ public static class FilesEndpoints
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return Results.NotFound(new { error = "Файл не найден или ошибка доступа.", message = ex.Message });
|
||||
return Results.NotFound(new { error = "Файл не найден", message = ex.Message });
|
||||
}
|
||||
});
|
||||
|
||||
// Новый эндпоинт для удаленных (федеративных) файлов
|
||||
group.MapGet("/remote/{domain}/{id}", async (string domain, string id, HttpClient httpClient, ISettingsService settingsService, CancellationToken ct) =>
|
||||
{
|
||||
var settings = await settingsService.GetSettingsAsync(ct);
|
||||
if (!settings.Federation.Enabled) return Results.Forbid();
|
||||
|
||||
// Формируем подписанный запрос к удаленному серверу
|
||||
var targetUrl = $"{domain.TrimEnd('/')}/api/federation/v1/proxy/{id}";
|
||||
|
||||
var request = new HttpRequestMessage(HttpMethod.Get, targetUrl);
|
||||
request.Headers.Add("X-Knot-Domain", settings.System.DomainUrl);
|
||||
|
||||
// Генерируем подпись запроса своим приватным ключом
|
||||
using (var rsa = RSA.Create())
|
||||
{
|
||||
rsa.ImportPkcs8PrivateKey(Convert.FromBase64String(settings.Federation.PrivateKey!), out _);
|
||||
var dataToSign = Encoding.UTF8.GetBytes(id + settings.System.DomainUrl);
|
||||
var signature = Convert.ToBase64String(rsa.SignData(dataToSign, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1));
|
||||
request.Headers.Add("X-Knot-Signature", signature);
|
||||
}
|
||||
|
||||
var response = await httpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, ct);
|
||||
if (!response.IsSuccessStatusCode) return Results.NotFound();
|
||||
|
||||
var remoteStream = await response.Content.ReadAsStreamAsync(ct);
|
||||
var contentType = response.Content.Headers.ContentType?.ToString() ?? "application/octet-stream";
|
||||
|
||||
return Results.Stream(remoteStream, contentType, enableRangeProcessing: true);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user