From e276162845f7f88405b32dd8bc8154f49d94b647 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A9=20Dupuis?= <1518299+JoeDupuis@users.noreply.github.com> Date: Mon, 19 May 2025 16:59:02 -0700 Subject: [PATCH 1/4] Ensure unique blob names in client tests --- test/client/test_client.rb | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/test/client/test_client.rb b/test/client/test_client.rb index 9fac222..66fdd3c 100644 --- a/test/client/test_client.rb +++ b/test/client/test_client.rb @@ -22,7 +22,8 @@ def setup principal_id: @principal_id, host: @host, ) - @key = "test client##{name}" + @uid = SecureRandom.uuid + @key = "test-client-#{name}-#{@uid}" @content = "Some random content #{Random.rand(200)}" end @@ -197,9 +198,9 @@ def test_delete end def test_delete_prefix - prefix = "#{name}_prefix" + prefix = "#{name}_prefix_#{@uid}" keys = 4.times.map do |i| - key = "#{prefix}/#{name}_#{i}" + key = "#{prefix}/#{i}" client.create_block_blob(key, content) key end @@ -212,7 +213,7 @@ def test_delete_prefix end def test_list_prefix - prefix = "#{name}_prefix" + prefix = "#{name}_prefix_#{@uid}" @key = "#{prefix}/#{key}" client.create_block_blob(key, content) @@ -222,9 +223,9 @@ def test_list_prefix end def test_list_blobs_with_pages - prefix = "#{name}_prefix" + prefix = "#{name}_prefix_#{@uid}" keys = 4.times.map do |i| - key = "#{prefix}/#{name}_#{i}" + key = "#{prefix}/#{i}" client.create_block_blob(key, content) key end From 28ad783189d512bf52015626b111730ae4822476 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A9=20Dupuis?= Date: Mon, 19 May 2025 18:43:38 -0700 Subject: [PATCH 2/4] Fix escaping issue --- lib/azure_blob/client.rb | 6 ++++-- test/client/test_client.rb | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/lib/azure_blob/client.rb b/lib/azure_blob/client.rb index 3f35c9a..1edb29b 100644 --- a/lib/azure_blob/client.rb +++ b/lib/azure_blob/client.rb @@ -194,7 +194,8 @@ def blob_exist?(key, options = {}) # # Returns a hash of the blob's tags. def get_blob_tags(key) - uri = generate_uri("#{container}/#{key}?comp=tags") + uri = generate_uri("#{container}/#{key}") + uri.query = URI.encode_www_form(comp: "tags") response = Http.new(uri, signer:).get Tags.from_response(response).to_h @@ -246,7 +247,8 @@ def delete_container(options = {}) # # Example: +generate_uri("#{container}/#{key}")+ def generate_uri(path) - URI.parse(URI::RFC2396_PARSER.escape(File.join(host, path))) + encoded = path.split("/").map { |segment| CGI.escape(segment) }.join("/") + URI.parse([host.chomp("/"), encoded].join("/")) end # Returns an SAS signed URI diff --git a/test/client/test_client.rb b/test/client/test_client.rb index 66fdd3c..54095f7 100644 --- a/test/client/test_client.rb +++ b/test/client/test_client.rb @@ -23,7 +23,7 @@ def setup host: @host, ) @uid = SecureRandom.uuid - @key = "test-client-#{name}-#{@uid}" + @key = "test-client-?-#{name}-#{@uid}" # ? in key to test proper escaping @content = "Some random content #{Random.rand(200)}" end From f6a18d60623d367308a19bd1adfc73f554850ec3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A9=20Dupuis?= Date: Mon, 19 May 2025 18:47:57 -0700 Subject: [PATCH 3/4] Update changelog --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6e76dbd..bf6174e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,8 @@ ## [Unreleased] +- Fix typo in class name `AzureBlob::ForbidenError` to `AzureBlob::ForbiddenError` +- Fix proper URI encoding for keys with special characters like question marks + ## [0.5.8] 2025-05-14 - Add support for copying blobs across containers (#24) From 5976de3b11787fe269e56eae0f3da114eefcc7f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A9=20Dupuis?= Date: Mon, 19 May 2025 18:49:14 -0700 Subject: [PATCH 4/4] Lint --- lib/azure_blob/client.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/azure_blob/client.rb b/lib/azure_blob/client.rb index 1edb29b..9d1b7f2 100644 --- a/lib/azure_blob/client.rb +++ b/lib/azure_blob/client.rb @@ -248,7 +248,7 @@ def delete_container(options = {}) # Example: +generate_uri("#{container}/#{key}")+ def generate_uri(path) encoded = path.split("/").map { |segment| CGI.escape(segment) }.join("/") - URI.parse([host.chomp("/"), encoded].join("/")) + URI.parse([ host.chomp("/"), encoded ].join("/")) end # Returns an SAS signed URI