diff --git a/src/Speckle.Sdk/Api/Blob/BlobApi.cs b/src/Speckle.Sdk/Api/Blob/BlobApi.cs index 1dd68eb5..10939f6d 100644 --- a/src/Speckle.Sdk/Api/Blob/BlobApi.cs +++ b/src/Speckle.Sdk/Api/Blob/BlobApi.cs @@ -193,30 +193,7 @@ public sealed class BlobApi : IBlobApi using var response = await _unauthedClient.SendAsync(requestMessage, cancellationToken).ConfigureAwait(false); response.EnsureSuccessStatusCode(); - return ParseEtagHeader(response.Headers); - } - - private static string ParseEtagHeader(HttpResponseHeaders headers) - { - if (!headers.TryGetValues("ETag", out var etagValues)) - { - throw new ArgumentException( - "Response does not have an ETag attached to it, cannot use this as an upload", - nameof(headers) - ); - } - - var etagValuesArray = etagValues.ToArray(); - - if (etagValuesArray.Length != 1) - { - throw new ArgumentException( - $"Expected Etag header to have a single value but got {etagValuesArray.Length}", - nameof(headers) - ); - } - - return etagValuesArray[0]; + return BlobApiHelpers.ParseEtagHeader(response.Headers); } /// diff --git a/src/Speckle.Sdk/Helpers/BlobApiHelpers.cs b/src/Speckle.Sdk/Helpers/BlobApiHelpers.cs new file mode 100644 index 00000000..c7979567 --- /dev/null +++ b/src/Speckle.Sdk/Helpers/BlobApiHelpers.cs @@ -0,0 +1,29 @@ +using System.Net.Http.Headers; + +namespace Speckle.Sdk.Helpers; + +public static class BlobApiHelpers +{ + public static string ParseEtagHeader(HttpResponseHeaders headers) + { + if (!headers.TryGetValues("ETag", out var etagValues)) + { + throw new ArgumentException( + "Response does not have an ETag attached to it, cannot use this as an upload", + nameof(headers) + ); + } + + var etagValuesArray = etagValues.ToArray(); + + if (etagValuesArray.Length != 1) + { + throw new ArgumentException( + $"Expected Etag header to have a single value but got {etagValuesArray.Length}", + nameof(headers) + ); + } + + return etagValuesArray[0]; + } +} diff --git a/src/Speckle.Sdk/Pipelines/Send/Uploader.cs b/src/Speckle.Sdk/Pipelines/Send/Uploader.cs index 63a17881..1cd4f8f4 100644 --- a/src/Speckle.Sdk/Pipelines/Send/Uploader.cs +++ b/src/Speckle.Sdk/Pipelines/Send/Uploader.cs @@ -1,4 +1,5 @@ using System.Net.Http.Headers; +using System.Text; using Microsoft.Extensions.Logging; using Speckle.InterfaceGenerator; using Speckle.Newtonsoft.Json; @@ -54,9 +55,9 @@ public sealed class Uploader : IDisposable public async Task Send(Stream fileStream) { PresignedUploadResponse presignedUploadResponse = await GetPresignedUrl().ConfigureAwait(false); - await UploadToS3(fileStream, presignedUploadResponse).ConfigureAwait(false); + var etag = await UploadToS3(fileStream, presignedUploadResponse).ConfigureAwait(false); - await TriggerProcessing().ConfigureAwait(false); + await TriggerProcessing(new() { Etag = etag }).ConfigureAwait(false); } private async Task GetPresignedUrl() @@ -77,7 +78,7 @@ public sealed class Uploader : IDisposable return presignedUpload; } - private async Task UploadToS3(Stream fileStream, PresignedUploadResponse presignedUploadResponse) + private async Task UploadToS3(Stream fileStream, PresignedUploadResponse presignedUploadResponse) { _logger.LogInformation("Uploading file to pre-signed url"); @@ -100,16 +101,21 @@ public sealed class Uploader : IDisposable .ConfigureAwait(false); uploadResponse.EnsureSuccessStatusCode(); + + return BlobApiHelpers.ParseEtagHeader(uploadResponse.Headers); } - private async Task TriggerProcessing() + private async Task TriggerProcessing(TriggerUploadRequest request) { Uri processUri = new($"projects/{_projectId}/modelingestion/{_ingestionId}/uploads/process", UriKind.Relative); + string requestBody = JsonConvert.SerializeObject(request); + using var content = new StringContent(requestBody, Encoding.UTF8, "application/json"); using HttpResponseMessage processResponse = await _speckleClient - .PostAsync(processUri, null, _cancellationToken) + .PostAsync(processUri, content, _cancellationToken) .ConfigureAwait(false); + string body = await processResponse.Content.ReadAsStringAsync().ConfigureAwait(false); processResponse.EnsureSuccessStatusCode(); } diff --git a/src/Speckle.Sdk/Pipelines/Send/UploaderDTOs.cs b/src/Speckle.Sdk/Pipelines/Send/UploaderDTOs.cs index 8ff9a546..11df1420 100644 --- a/src/Speckle.Sdk/Pipelines/Send/UploaderDTOs.cs +++ b/src/Speckle.Sdk/Pipelines/Send/UploaderDTOs.cs @@ -1,3 +1,4 @@ +using Speckle.Newtonsoft.Json; using Speckle.Sdk.Models; using Speckle.Sdk.Serialisation; @@ -12,7 +13,8 @@ internal record PresignedUploadResponse public Dictionary AdditionalRequestHeaders { get; init; } = new(); } -internal record ProcessUploadResponse +internal readonly struct TriggerUploadRequest { - public required string ingestionId { get; init; } + [JsonProperty("etag")] + public required string Etag { get; init; } }