Redirect from file store for direct serve

This commit is contained in:
Kieran
2022-07-25 19:46:14 +01:00
parent 99907fce8b
commit 3b1bf9f12d
8 changed files with 49 additions and 16 deletions

View File

@@ -75,6 +75,15 @@ public class DownloadController : Controller
Response.ContentLength = range.Size; Response.ContentLength = range.Size;
} }
var preResult = await _storage.StartEgress(egressReq);
if (preResult.Redirect != null)
{
Response.StatusCode = (int)HttpStatusCode.Redirect;
Response.Headers.Location = preResult.Redirect.ToString();
Response.ContentLength = 0;
return;
}
var cts = HttpContext.RequestAborted; var cts = HttpContext.RequestAborted;
await Response.StartAsync(cts); await Response.StartAsync(cts);
await _storage.Egress(egressReq, Response.Body, cts); await _storage.Egress(egressReq, Response.Body, cts);

View File

@@ -1,7 +1,5 @@
using VoidCat.Services.Abstractions;
namespace VoidCat.Model; namespace VoidCat.Model;
public sealed record EgressRequest(Guid Id, IEnumerable<RangeRequest> Ranges) public sealed record EgressRequest(Guid Id, IEnumerable<RangeRequest> Ranges);
{
} public sealed record EgressResult(Uri? Redirect = null);

View File

@@ -29,6 +29,13 @@ public interface IFileStore
/// <returns></returns> /// <returns></returns>
ValueTask Egress(EgressRequest request, Stream outStream, CancellationToken cts); ValueTask Egress(EgressRequest request, Stream outStream, CancellationToken cts);
/// <summary>
/// Pre-Egress checks
/// </summary>
/// <param name="request"></param>
/// <returns></returns>
ValueTask<EgressResult> StartEgress(EgressRequest request);
/// <summary> /// <summary>
/// Deletes file data only, metadata must be deleted with <see cref="IFileInfoManager.Delete"/> /// Deletes file data only, metadata must be deleted with <see cref="IFileInfoManager.Delete"/>
/// </summary> /// </summary>

View File

@@ -54,6 +54,13 @@ public class FileStoreFactory : IFileStore
await store.Egress(request, outStream, cts); await store.Egress(request, outStream, cts);
} }
/// <inheritdoc />
public async ValueTask<EgressResult> StartEgress(EgressRequest request)
{
var store = await GetStore(request.Id);
return await store.StartEgress(request);
}
/// <inheritdoc /> /// <inheritdoc />
public async ValueTask DeleteFile(Guid id) public async ValueTask DeleteFile(Guid id)
{ {

View File

@@ -31,6 +31,12 @@ public class LocalDiskFileStore : StreamFileStore, IFileStore
await EgressFromStream(fs, request, outStream, cts); await EgressFromStream(fs, request, outStream, cts);
} }
/// <inheritdoc />
public ValueTask<EgressResult> StartEgress(EgressRequest request)
{
return ValueTask.FromResult(new EgressResult());
}
/// <inheritdoc /> /// <inheritdoc />
public string Key => "local-disk"; public string Key => "local-disk";

View File

@@ -143,15 +143,6 @@ public class S3FileMetadataStore : IFileMetadataStore
if (ret != default) if (ret != default)
{ {
ret.Id = id; ret.Id = id;
if (_config.Direct)
{
var ub = new UriBuilder(_config.ServiceUrl!)
{
Path = $"/{_config.BucketName}/{id}"
};
ret.Url = ub.Uri;
}
} }
return ret; return ret;

View File

@@ -61,6 +61,19 @@ public class S3FileStore : StreamFileStore, IFileStore
await EgressFull(request.Id, stream, outStream, cts); await EgressFull(request.Id, stream, outStream, cts);
} }
/// <inheritdoc />
public ValueTask<EgressResult> StartEgress(EgressRequest request)
{
if (!_config.Direct) return ValueTask.FromResult(new EgressResult());
var ub = new UriBuilder(_config.ServiceUrl!)
{
Path = $"/{_config.BucketName}/{request.Id}"
};
return ValueTask.FromResult(new EgressResult(ub.Uri));
}
public async ValueTask<PagedResult<PublicVoidFile>> ListFiles(PagedRequest request) public async ValueTask<PagedResult<PublicVoidFile>> ListFiles(PagedRequest request)
{ {
try try

View File

@@ -19,7 +19,9 @@ export default function ApiKeyList() {
let rsp = await Api.createApiKey({ let rsp = await Api.createApiKey({
expiry: new Date(new Date().getTime() + DefaultExpiry) expiry: new Date(new Date().getTime() + DefaultExpiry)
}); });
setNewApiKey(await rsp.json()); if (rsp.ok) {
setNewApiKey(await rsp.json());
}
} }
useEffect(() => { useEffect(() => {
@@ -59,7 +61,7 @@ export default function ApiKeyList() {
</tbody> </tbody>
</table> </table>
{newApiKey ? {newApiKey ?
<VoidModal title="New Api Key" style={{ maxWidth: "50vw"}}> <VoidModal title="New Api Key" style={{maxWidth: "50vw"}}>
Please save this now as it will not be shown again: Please save this now as it will not be shown again:
<pre className="copy">{newApiKey.token}</pre> <pre className="copy">{newApiKey.token}</pre>
<VoidButton onClick={(e) => setNewApiKey(undefined)}>Close</VoidButton> <VoidButton onClick={(e) => setNewApiKey(undefined)}>Close</VoidButton>