diff --git a/AspNetCore.Yandex.ObjectStorage.IntegrationTests/ObjectServiceTests.cs b/AspNetCore.Yandex.ObjectStorage.IntegrationTests/ObjectServiceTests.cs index a3dcbe6..8c907e2 100644 --- a/AspNetCore.Yandex.ObjectStorage.IntegrationTests/ObjectServiceTests.cs +++ b/AspNetCore.Yandex.ObjectStorage.IntegrationTests/ObjectServiceTests.cs @@ -3,6 +3,7 @@ using System.Net; using System.Threading.Tasks; using AspNetCore.Yandex.ObjectStorage.Models; +using AspNetCore.Yandex.ObjectStorage.Object.Models; using Bogus; using Xunit; @@ -163,7 +164,7 @@ public async Task PutObject_NotDefaultLocation_Success() #region Private - private async Task TryGetObjectAsync(string filename) + private async Task TryGetObjectAsync(string filename) { return await _yandexStorageService.TryGetAsync(filename); } diff --git a/AspNetCore.Yandex.ObjectStorage/AspNetCore.Yandex.ObjectStorage.csproj b/AspNetCore.Yandex.ObjectStorage/AspNetCore.Yandex.ObjectStorage.csproj index de61342..7af3fdb 100644 --- a/AspNetCore.Yandex.ObjectStorage/AspNetCore.Yandex.ObjectStorage.csproj +++ b/AspNetCore.Yandex.ObjectStorage/AspNetCore.Yandex.ObjectStorage.csproj @@ -9,15 +9,15 @@ https://github.com/DubZero/AspNetCore.Yandex.ObjectStorage git S3, Yandex, Object Storage - + Impliment core bucket service functions false false https://yastatic.net/q/cloud-www/build/ru/assets/img/storage.15691e8c.png - 0.2.0.1 - 0.2.0.1 + 0.2.1 + 0.2.1 LICENSE.md true - 0.2.0.1-alpha001 + 0.2.1.0 netstandard2.1 Yandex.ObjectStorage S3 API Client Library diff --git a/AspNetCore.Yandex.ObjectStorage/Bucket/BucketService.cs b/AspNetCore.Yandex.ObjectStorage/Bucket/BucketService.cs index 6e7a579..0ec86ee 100644 --- a/AspNetCore.Yandex.ObjectStorage/Bucket/BucketService.cs +++ b/AspNetCore.Yandex.ObjectStorage/Bucket/BucketService.cs @@ -8,6 +8,7 @@ using AspNetCore.Yandex.ObjectStorage.Configuration; using AspNetCore.Yandex.ObjectStorage.Enums; using AspNetCore.Yandex.ObjectStorage.Models; +using AspNetCore.Yandex.ObjectStorage.Object.Models; using Microsoft.Extensions.Options; namespace AspNetCore.Yandex.ObjectStorage.Bucket @@ -27,7 +28,7 @@ public BucketService(YandexStorageOptions options) _options = options; } - public async Task CreateBucket(string bucketName) + public async Task CreateBucket(string bucketName) { var builder = new BucketPutRequestBuilder(_options); var requestMessage = builder.Build(bucketName).GetResult(); @@ -35,12 +36,19 @@ public async Task CreateBucket(string bucketName) using var client = new HttpClient(); var response = await client.SendAsync(requestMessage); - return new S3PutResponse(response, GetBucketUri(bucketName)); + return new S3ObjectPutResponse(response, GetBucketUri(bucketName)); } - public Task GetBucketMeta(string bucketName) + public async Task GetBucketMeta(string bucketName) { - throw new NotImplementedException(); + var requestMessage = new BucketMetaRequestBuilder(_options) + .Build(bucketName) + .GetResult(); + + using var client = new HttpClient(); + var response = await client.SendAsync(requestMessage); + + return new S3Response(response); } public async Task GetBucketListObjects(BucketListObjectsParameters parameters) @@ -66,7 +74,7 @@ public async Task GetBucketList() return new S3BucketListResponse(response); } - public async Task DeleteBucket(string bucketName) + public async Task DeleteBucket(string bucketName) { var builder = new BucketDeleteRequestBuilder(_options); var requestMessage = builder.Build(bucketName).GetResult(); @@ -74,7 +82,7 @@ public async Task DeleteBucket(string bucketName) using var client = new HttpClient(); var response = await client.SendAsync(requestMessage); - return new S3DeleteResponse(response); + return new S3ObjectDeleteResponse(response); } private string GetBucketUri(string bucket) diff --git a/AspNetCore.Yandex.ObjectStorage/Bucket/Builders/BucketMetaRequestBuilder.cs b/AspNetCore.Yandex.ObjectStorage/Bucket/Builders/BucketMetaRequestBuilder.cs new file mode 100644 index 0000000..b84f67f --- /dev/null +++ b/AspNetCore.Yandex.ObjectStorage/Bucket/Builders/BucketMetaRequestBuilder.cs @@ -0,0 +1,40 @@ +using System; +using System.Net.Http; +using AspNetCore.Yandex.ObjectStorage.Bucket.Requests; +using AspNetCore.Yandex.ObjectStorage.Configuration; +using AspNetCore.Yandex.ObjectStorage.Helpers; + +namespace AspNetCore.Yandex.ObjectStorage.Bucket.Builders +{ + internal class BucketMetaRequestBuilder + { + private readonly YandexStorageOptions _options; + private HttpRequestMessage _request; + + internal BucketMetaRequestBuilder(YandexStorageOptions options) + { + _options = options; + } + + internal BucketMetaRequestBuilder Build(string bucketName) + { + var url = $"{_options.Protocol}://{_options.Endpoint}/{bucketName}"; + + var requestMessage = new HttpRequestMessage(HttpMethod.Head, new Uri(url)); + var dateAmz = DateTime.UtcNow; + + requestMessage.AddBothHeaders(_options, dateAmz); + + string[] headers = { "host", "x-amz-content-sha256", "x-amz-date" }; + requestMessage.AddAuthHeader(_options, dateAmz, headers); + _request = requestMessage; + + return this; + } + + internal HttpRequestMessage GetResult() + { + return _request; + } + } +} \ No newline at end of file diff --git a/AspNetCore.Yandex.ObjectStorage/Bucket/IBucketService.cs b/AspNetCore.Yandex.ObjectStorage/Bucket/IBucketService.cs index d6f49ce..43d65aa 100644 --- a/AspNetCore.Yandex.ObjectStorage/Bucket/IBucketService.cs +++ b/AspNetCore.Yandex.ObjectStorage/Bucket/IBucketService.cs @@ -2,19 +2,33 @@ using AspNetCore.Yandex.ObjectStorage.Bucket.Requests; using AspNetCore.Yandex.ObjectStorage.Bucket.Responses; using AspNetCore.Yandex.ObjectStorage.Models; +using AspNetCore.Yandex.ObjectStorage.Object.Models; namespace AspNetCore.Yandex.ObjectStorage.Bucket { public interface IBucketService { - Task CreateBucket(string bucketName); + Task CreateBucket(string bucketName); - Task GetBucketMeta(string bucketName); + /// + /// Returns the bucket's metadata or an error. + /// Use this method to check: + /// 1. Whether the bucket exists. + /// 2. Whether the user has sufficient permissions to access the bucket + /// + Task GetBucketMeta(string bucketName); + + /// + /// Get list of objects in bucket + /// Task GetBucketListObjects(BucketListObjectsParameters parameters); + /// + /// Get list of buckets + /// Task GetBucketList(); - Task DeleteBucket(string bucketName); + Task DeleteBucket(string bucketName); } } \ No newline at end of file diff --git a/AspNetCore.Yandex.ObjectStorage/IYandexStorageService.cs b/AspNetCore.Yandex.ObjectStorage/IYandexStorageService.cs index 96be024..5f9e3bb 100644 --- a/AspNetCore.Yandex.ObjectStorage/IYandexStorageService.cs +++ b/AspNetCore.Yandex.ObjectStorage/IYandexStorageService.cs @@ -2,6 +2,7 @@ using AspNetCore.Yandex.ObjectStorage.Bucket; using AspNetCore.Yandex.ObjectStorage.Models; using AspNetCore.Yandex.ObjectStorage.Object; +using AspNetCore.Yandex.ObjectStorage.Object.Models; namespace AspNetCore.Yandex.ObjectStorage { @@ -19,11 +20,11 @@ public interface IYandexStorageService /// Test connection to storage /// /// Retruns true if all credentials correct - Task TryConnectAsync(); + Task TryConnectAsync(); /// /// Test connection to storage /// /// Retruns true if all credentials correct - Task TryGetAsync(string filename); + Task TryGetAsync(string filename); } } \ No newline at end of file diff --git a/AspNetCore.Yandex.ObjectStorage/Models/S3Response.cs b/AspNetCore.Yandex.ObjectStorage/Models/S3Response.cs new file mode 100644 index 0000000..7fd635e --- /dev/null +++ b/AspNetCore.Yandex.ObjectStorage/Models/S3Response.cs @@ -0,0 +1,23 @@ +using System.Net.Http; +using System.Threading.Tasks; +using FluentResults; + +namespace AspNetCore.Yandex.ObjectStorage.Models +{ + public class S3Response : BaseS3Response + { + public S3Response(HttpResponseMessage response) : base(response) + { + } + + public async Task> ReadResultAsStringAsync() + { + if (IsSuccessStatusCode) + { + return await Response.Content.ReadAsStringAsync(); + } + + return Result.Fail(await Response.Content.ReadAsStringAsync()); + } + } +} \ No newline at end of file diff --git a/AspNetCore.Yandex.ObjectStorage/Object/IObjectService.cs b/AspNetCore.Yandex.ObjectStorage/Object/IObjectService.cs index 0f726d6..13a2b3c 100644 --- a/AspNetCore.Yandex.ObjectStorage/Object/IObjectService.cs +++ b/AspNetCore.Yandex.ObjectStorage/Object/IObjectService.cs @@ -2,13 +2,14 @@ using System.IO; using System.Threading.Tasks; using AspNetCore.Yandex.ObjectStorage.Models; +using AspNetCore.Yandex.ObjectStorage.Object.Models; using FluentResults; namespace AspNetCore.Yandex.ObjectStorage.Object { public interface IObjectService { - Task GetAsync(string filename); + Task GetAsync(string filename); Task> GetAsByteArrayAsync(string filename); @@ -25,10 +26,10 @@ public interface IObjectService /// /// Put ob /// - Task PutAsync(Stream stream, string filename); + Task PutAsync(Stream stream, string filename); - Task PutAsync(byte[] byteArr, string filename); + Task PutAsync(byte[] byteArr, string filename); - Task DeleteAsync(string filename); + Task DeleteAsync(string filename); } } \ No newline at end of file diff --git a/AspNetCore.Yandex.ObjectStorage/Models/S3DeleteResponse.cs b/AspNetCore.Yandex.ObjectStorage/Object/Models/S3ObjectDeleteResponse.cs similarity index 60% rename from AspNetCore.Yandex.ObjectStorage/Models/S3DeleteResponse.cs rename to AspNetCore.Yandex.ObjectStorage/Object/Models/S3ObjectDeleteResponse.cs index 02ab197..bf7c9d6 100644 --- a/AspNetCore.Yandex.ObjectStorage/Models/S3DeleteResponse.cs +++ b/AspNetCore.Yandex.ObjectStorage/Object/Models/S3ObjectDeleteResponse.cs @@ -1,13 +1,14 @@ using System.Net.Http; using System.Threading.Tasks; +using AspNetCore.Yandex.ObjectStorage.Models; using FluentResults; -namespace AspNetCore.Yandex.ObjectStorage.Models +namespace AspNetCore.Yandex.ObjectStorage.Object.Models { - public class S3DeleteResponse : BaseS3Response + public class S3ObjectDeleteResponse : BaseS3Response { - public S3DeleteResponse(HttpResponseMessage response) : base(response) + public S3ObjectDeleteResponse(HttpResponseMessage response) : base(response) { } diff --git a/AspNetCore.Yandex.ObjectStorage/Models/S3GetResponse.cs b/AspNetCore.Yandex.ObjectStorage/Object/Models/S3ObjectGetResponse.cs similarity index 75% rename from AspNetCore.Yandex.ObjectStorage/Models/S3GetResponse.cs rename to AspNetCore.Yandex.ObjectStorage/Object/Models/S3ObjectGetResponse.cs index dab7ba6..32e8609 100644 --- a/AspNetCore.Yandex.ObjectStorage/Models/S3GetResponse.cs +++ b/AspNetCore.Yandex.ObjectStorage/Object/Models/S3ObjectGetResponse.cs @@ -1,13 +1,14 @@ using System.IO; using System.Net.Http; using System.Threading.Tasks; +using AspNetCore.Yandex.ObjectStorage.Models; using FluentResults; -namespace AspNetCore.Yandex.ObjectStorage.Models +namespace AspNetCore.Yandex.ObjectStorage.Object.Models { - public class S3GetResponse : BaseS3Response + public class S3ObjectGetResponse : BaseS3Response { - public S3GetResponse(HttpResponseMessage response) : base(response) + public S3ObjectGetResponse(HttpResponseMessage response) : base(response) { } diff --git a/AspNetCore.Yandex.ObjectStorage/Models/S3PutResponse.cs b/AspNetCore.Yandex.ObjectStorage/Object/Models/S3ObjectPutResponse.cs similarity index 69% rename from AspNetCore.Yandex.ObjectStorage/Models/S3PutResponse.cs rename to AspNetCore.Yandex.ObjectStorage/Object/Models/S3ObjectPutResponse.cs index 6b96e31..cbc8e66 100644 --- a/AspNetCore.Yandex.ObjectStorage/Models/S3PutResponse.cs +++ b/AspNetCore.Yandex.ObjectStorage/Object/Models/S3ObjectPutResponse.cs @@ -1,14 +1,15 @@ using System.Net.Http; using System.Threading.Tasks; +using AspNetCore.Yandex.ObjectStorage.Models; using FluentResults; -namespace AspNetCore.Yandex.ObjectStorage.Models +namespace AspNetCore.Yandex.ObjectStorage.Object.Models { - public class S3PutResponse : BaseS3Response + public class S3ObjectPutResponse : BaseS3Response { private readonly string _url; - public S3PutResponse(HttpResponseMessage response, string url) : base(response) + public S3ObjectPutResponse(HttpResponseMessage response, string url) : base(response) { _url = url; } diff --git a/AspNetCore.Yandex.ObjectStorage/Object/ObjectService.cs b/AspNetCore.Yandex.ObjectStorage/Object/ObjectService.cs index 240b1b9..cd844ae 100644 --- a/AspNetCore.Yandex.ObjectStorage/Object/ObjectService.cs +++ b/AspNetCore.Yandex.ObjectStorage/Object/ObjectService.cs @@ -5,6 +5,7 @@ using AspNetCore.Yandex.ObjectStorage.Configuration; using AspNetCore.Yandex.ObjectStorage.Helpers; using AspNetCore.Yandex.ObjectStorage.Models; +using AspNetCore.Yandex.ObjectStorage.Object.Models; using FluentResults; using Microsoft.Extensions.Options; @@ -45,13 +46,13 @@ public ObjectService(YandexStorageOptions options) _hostName = options.HostName; } - public async Task GetAsync(string filename) + public async Task GetAsync(string filename) { var formattedPath = FormatPath(filename); var requestMessage = PrepareGetRequest(formattedPath); - var response = new S3GetResponse(await _client.SendAsync(requestMessage)); + var response = new S3ObjectGetResponse(await _client.SendAsync(requestMessage)); return response; } @@ -67,7 +68,7 @@ public async Task> GetAsByteArrayAsync(string filename) var requestMessage = PrepareGetRequest(formattedPath); - var response = new S3GetResponse(await _client.SendAsync(requestMessage)); + var response = new S3ObjectGetResponse(await _client.SendAsync(requestMessage)); return await response.ReadAsByteArrayAsync().ConfigureAwait(false); } @@ -82,12 +83,12 @@ public async Task> GetAsStreamAsync(string filename) var formattedPath = FormatPath(filename); var requestMessage = PrepareGetRequest(formattedPath); - var response = new S3GetResponse(await _client.SendAsync(requestMessage, HttpCompletionOption.ResponseHeadersRead)); + var response = new S3ObjectGetResponse(await _client.SendAsync(requestMessage, HttpCompletionOption.ResponseHeadersRead)); return await response.ReadAsStreamAsync().ConfigureAwait(false); } - public async Task PutAsync(Stream stream, string filename) + public async Task PutAsync(Stream stream, string filename) { var formattedPath = FormatPath(filename); @@ -95,10 +96,10 @@ public async Task PutAsync(Stream stream, string filename) var response = await _client.SendAsync(requestMessage); - return new S3PutResponse(response, GetObjectUri(formattedPath)); + return new S3ObjectPutResponse(response, GetObjectUri(formattedPath)); } - public async Task PutAsync(byte[] byteArr, string filename) + public async Task PutAsync(byte[] byteArr, string filename) { var formattedPath = FormatPath(filename); @@ -106,10 +107,10 @@ public async Task PutAsync(byte[] byteArr, string filename) var response = await _client.SendAsync(requestMessage); - return new S3PutResponse(response, GetObjectUri(formattedPath)); + return new S3ObjectPutResponse(response, GetObjectUri(formattedPath)); } - public async Task DeleteAsync(string filename) + public async Task DeleteAsync(string filename) { var formattedPath = FormatPath(filename); @@ -117,7 +118,7 @@ public async Task DeleteAsync(string filename) var response = await _client.SendAsync(requestMessage); - return new S3DeleteResponse(response); + return new S3ObjectDeleteResponse(response); } private HttpRequestMessage PrepareGetRequest() diff --git a/AspNetCore.Yandex.ObjectStorage/YandexStorageService.cs b/AspNetCore.Yandex.ObjectStorage/YandexStorageService.cs index 7544b61..f200494 100644 --- a/AspNetCore.Yandex.ObjectStorage/YandexStorageService.cs +++ b/AspNetCore.Yandex.ObjectStorage/YandexStorageService.cs @@ -6,6 +6,7 @@ using AspNetCore.Yandex.ObjectStorage.Models; using AspNetCore.Yandex.ObjectStorage.Multipart; using AspNetCore.Yandex.ObjectStorage.Object; +using AspNetCore.Yandex.ObjectStorage.Object.Models; using Microsoft.Extensions.Options; namespace AspNetCore.Yandex.ObjectStorage @@ -52,26 +53,26 @@ public YandexStorageService(YandexStorageOptions options) _hostName = options.HostName; } - public async Task TryConnectAsync() + public async Task TryConnectAsync() { var requestMessage = PrepareGetRequest(); var response = await _client.SendAsync(requestMessage, HttpCompletionOption.ResponseHeadersRead); - return new S3GetResponse(response); + return new S3ObjectGetResponse(response); } /// /// Test connection to storage /// /// Retruns true if all credentials correct - public async Task TryGetAsync(string filename) + public async Task TryGetAsync(string filename) { var requestMessage = PrepareGetRequest(filename); var response = await _client.SendAsync(requestMessage, HttpCompletionOption.ResponseHeadersRead); - return new S3GetResponse(response); + return new S3ObjectGetResponse(response); } private HttpRequestMessage PrepareGetRequest() diff --git a/README.md b/README.md index 840a4c9..c92442b 100644 --- a/README.md +++ b/README.md @@ -56,7 +56,21 @@ Stream stream = await _objectStoreService.GetAsStreamAsync(filename); ## List of implemented API methods -### Bucket Service ❌ - not implemented +### Bucket Service +- create - Creates a bucket ✅ implemented +- getMeta - Returns the bucket's metadata or an error ✅ implemented +- listObjects - Returns a list of bucket objects. Pagination is used for output ✅ implemented +- listBuckets - Returns a list of buckets available to the user ✅ implemented +- deleteBucket - Deletes an empty bucket. If the bucket isn't empty, first delete all the objects inside the bucket ✅ implemented +- getBucketEncryption - ❌ not implemented +- deleteBucketEncryption - ❌ not implemented +- putBucketEncryption - ❌ not implemented +- putBucketVersioning - ❌ not implemented +- getBucketVersioning - ❌ not implemented +- putBucketLogging - ❌ not implemented +- getBucketLogging - ❌ not implemented +- listObjectVersions - ❌ not implemented + ### Object service - upload Uploads an object to Object Storage. ✅ implemented - get Retrieves an object from Object Storage. ✅ implemented @@ -78,4 +92,4 @@ Stream stream = await _objectStoreService.GetAsStreamAsync(filename); ### CORS service ❌ - not implemented ### Lifecycles service ❌ - not implemented ### ACL service ❌ - not implemented -### Bucket Policy service ❌ - not implemented +### Bucket Policy service ❌ - not implemented \ No newline at end of file