From 7a6533dbcacc2bb6fc30524865086b4baba6e74f Mon Sep 17 00:00:00 2001 From: Edwin Goddard Date: Thu, 13 Jun 2024 09:09:39 +0100 Subject: [PATCH] Fix objects with spaces in name not returned correctly fixes #1100 (#1101) * Fix objects with spaces in name not returned correctly (#1100) The Uri.UnescapeDataString method has been replaced with the HttpUtility.UrlDecode method in the BucketOperations.cs file to correctly decode the URL. Additionally, the ListObjects_Test7 function has been added to the Program.cs and FunctionalTest.cs files to test whether ListObjects lists all objects matching a prefix with a space in a non-recursive manner. * fix formatting * Add test for prefix with a plus character * fix formatting --------- Co-authored-by: Edwin Goddard --- Minio.Functional.Tests/FunctionalTest.cs | 88 ++++++++++++++++++++++++ Minio.Functional.Tests/Program.cs | 2 + Minio/ApiEndpoints/BucketOperations.cs | 3 +- 3 files changed, 92 insertions(+), 1 deletion(-) diff --git a/Minio.Functional.Tests/FunctionalTest.cs b/Minio.Functional.Tests/FunctionalTest.cs index 3e45f0e0..e7393fd3 100644 --- a/Minio.Functional.Tests/FunctionalTest.cs +++ b/Minio.Functional.Tests/FunctionalTest.cs @@ -5292,6 +5292,94 @@ internal static async Task ListObjects_Test6(IMinioClient minio) } } + internal static async Task ListObjects_Test7(IMinioClient minio) + { + var startTime = DateTime.Now; + var bucketName = GetRandomName(15); + var prefix = "minix "; + var objectName = prefix + GetRandomName(10); + var args = new Dictionary + (StringComparer.Ordinal) + { + { "bucketName", bucketName }, + { "objectName", objectName }, + { "prefix", prefix }, + { "recursive", "false" } + }; + try + { + await Setup_Test(minio, bucketName).ConfigureAwait(false); + var tasks = new Task[2]; + for (var i = 0; i < 2; i++) + tasks[i] = PutObject_Task(minio, bucketName, objectName + i, null, null, 0, null, + rsg.GenerateStreamFromSeed(1)); + + await Task.WhenAll(tasks).ConfigureAwait(false); + + await ListObjects_Test(minio, bucketName, prefix, 2, false).ConfigureAwait(false); + new MintLogger("ListObjects_Test7", listObjectsSignature, + "Tests whether ListObjects lists all objects matching a prefix with a space non-recursive", + TestStatus.PASS, + DateTime.Now - startTime, args: args).Log(); + } + catch (Exception ex) + { + new MintLogger("ListObjects_Test7", listObjectsSignature, + "Tests whether ListObjects lists all objects matching a prefix with a space non-recursive", + TestStatus.FAIL, + DateTime.Now - startTime, ex.Message, ex.ToString(), args: args).Log(); + throw; + } + finally + { + await TearDown(minio, bucketName).ConfigureAwait(false); + } + } + + internal static async Task ListObjects_Test8(IMinioClient minio) + { + var startTime = DateTime.Now; + var bucketName = GetRandomName(15); + var prefix = "minix+"; + var objectName = prefix + GetRandomName(10); + var args = new Dictionary + (StringComparer.Ordinal) + { + { "bucketName", bucketName }, + { "objectName", objectName }, + { "prefix", prefix }, + { "recursive", "false" } + }; + try + { + await Setup_Test(minio, bucketName).ConfigureAwait(false); + var tasks = new Task[2]; + for (var i = 0; i < 2; i++) + tasks[i] = PutObject_Task(minio, bucketName, objectName + i, null, null, 0, null, + rsg.GenerateStreamFromSeed(1)); + + await Task.WhenAll(tasks).ConfigureAwait(false); + + await ListObjects_Test(minio, bucketName, prefix, 2, false).ConfigureAwait(false); + new MintLogger("ListObjects_Test8", listObjectsSignature, + "Tests whether ListObjects lists all objects matching a prefix with a plus non-recursive", + TestStatus.PASS, + DateTime.Now - startTime, args: args).Log(); + } + catch (Exception ex) + { + new MintLogger("ListObjects_Test8", listObjectsSignature, + "Tests whether ListObjects lists all objects matching a prefix with a plus non-recursive", + TestStatus.FAIL, + DateTime.Now - startTime, ex.Message, ex.ToString(), args: args).Log(); + throw; + } + finally + { + await TearDown(minio, bucketName).ConfigureAwait(false); + } + } + internal static async Task ListObjectVersions_Test1(IMinioClient minio) { var startTime = DateTime.Now; diff --git a/Minio.Functional.Tests/Program.cs b/Minio.Functional.Tests/Program.cs index 9cf302eb..20297e92 100644 --- a/Minio.Functional.Tests/Program.cs +++ b/Minio.Functional.Tests/Program.cs @@ -176,6 +176,8 @@ public static async Task Main(string[] args) functionalTestTasks.Add(FunctionalTest.ListObjects_Test4(minioClient)); functionalTestTasks.Add(FunctionalTest.ListObjects_Test5(minioClient)); functionalTestTasks.Add(FunctionalTest.ListObjects_Test6(minioClient)); + functionalTestTasks.Add(FunctionalTest.ListObjects_Test7(minioClient)); + functionalTestTasks.Add(FunctionalTest.ListObjects_Test8(minioClient)); // Test RemoveObjectAsync function functionalTestTasks.Add(FunctionalTest.RemoveObject_Test1(minioClient)); diff --git a/Minio/ApiEndpoints/BucketOperations.cs b/Minio/ApiEndpoints/BucketOperations.cs index 61abb0cd..95f1cb04 100644 --- a/Minio/ApiEndpoints/BucketOperations.cs +++ b/Minio/ApiEndpoints/BucketOperations.cs @@ -19,6 +19,7 @@ using System.Net; using System.Reactive.Linq; using System.Runtime.CompilerServices; +using System.Web; using System.Xml.Linq; using CommunityToolkit.HighPerformance; using Minio.ApiEndpoints; @@ -271,7 +272,7 @@ public async IAsyncEnumerable ListObjectsEnumAsync(ListObjectsArgs args, var objectKey = t.Element(ns + "Key")?.Value; if (objectKey != null) - objectKey = Uri.UnescapeDataString(objectKey); + objectKey = HttpUtility.UrlDecode(objectKey); return new Item {