fix path encoding issue (#794)
This commit is contained in:
parent
fda43987e4
commit
5bad554a06
@ -239,8 +239,8 @@ namespace Azure { namespace Storage { namespace Blobs {
|
||||
requestBody += getBatchBoundary();
|
||||
|
||||
auto blobUrl = m_serviceUrl;
|
||||
blobUrl.AppendPath(subrequest.ContainerName);
|
||||
blobUrl.AppendPath(subrequest.BlobName);
|
||||
blobUrl.AppendPath(Details::UrlEncodePath(subrequest.ContainerName));
|
||||
blobUrl.AppendPath(Details::UrlEncodePath(subrequest.BlobName));
|
||||
BlobRestClient::Blob::DeleteBlobOptions protocolLayerOptions;
|
||||
protocolLayerOptions.DeleteSnapshots = subrequest.Options.DeleteSnapshots;
|
||||
protocolLayerOptions.IfModifiedSince = subrequest.Options.AccessConditions.IfModifiedSince;
|
||||
@ -261,8 +261,8 @@ namespace Azure { namespace Storage { namespace Blobs {
|
||||
requestBody += getBatchBoundary();
|
||||
|
||||
auto blobUrl = m_serviceUrl;
|
||||
blobUrl.AppendPath(subrequest.ContainerName);
|
||||
blobUrl.AppendPath(subrequest.BlobName);
|
||||
blobUrl.AppendPath(Details::UrlEncodePath(subrequest.ContainerName));
|
||||
blobUrl.AppendPath(Details::UrlEncodePath(subrequest.BlobName));
|
||||
BlobRestClient::Blob::SetBlobAccessTierOptions protocolLayerOptions;
|
||||
protocolLayerOptions.Tier = subrequest.Tier;
|
||||
protocolLayerOptions.RehydratePriority = subrequest.Options.RehydratePriority;
|
||||
|
||||
@ -23,7 +23,7 @@ namespace Azure { namespace Storage { namespace Blobs {
|
||||
{
|
||||
auto parsedConnectionString = Details::ParseConnectionString(connectionString);
|
||||
auto containerUri = std::move(parsedConnectionString.BlobServiceUri);
|
||||
containerUri.AppendPath(containerName);
|
||||
containerUri.AppendPath(Details::UrlEncodePath(containerName));
|
||||
|
||||
if (parsedConnectionString.KeyCredential)
|
||||
{
|
||||
@ -117,7 +117,7 @@ namespace Azure { namespace Storage { namespace Blobs {
|
||||
BlobClient BlobContainerClient::GetBlobClient(const std::string& blobName) const
|
||||
{
|
||||
auto blobUri = m_containerUrl;
|
||||
blobUri.AppendPath(blobName);
|
||||
blobUri.AppendPath(Details::UrlEncodePath(blobName));
|
||||
return BlobClient(std::move(blobUri), m_pipeline, m_customerProvidedKey, m_encryptionScope);
|
||||
}
|
||||
|
||||
|
||||
@ -1,13 +1,13 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include "blob_container_client_test.hpp"
|
||||
#include "azure/storage/blobs/blob_sas_builder.hpp"
|
||||
#include "azure/storage/common/crypt.hpp"
|
||||
|
||||
#include <chrono>
|
||||
#include <thread>
|
||||
|
||||
#include "azure/storage/blobs/blob_sas_builder.hpp"
|
||||
#include "azure/storage/common/crypt.hpp"
|
||||
#include "blob_container_client_test.hpp"
|
||||
|
||||
namespace Azure { namespace Storage { namespace Blobs {
|
||||
|
||||
bool operator==(
|
||||
@ -1048,4 +1048,39 @@ namespace Azure { namespace Storage { namespace Test {
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(BlobContainerClientTest, SpecialBlobName)
|
||||
{
|
||||
const std::string non_ascii_word = "\xE6\xB5\x8B\xE8\xAF\x95";
|
||||
const std::string encoded_non_ascii_word = "%E6%B5%8B%E8%AF%95";
|
||||
std::string baseBlobName = "a b c / !@#$%^&*() def" + non_ascii_word;
|
||||
|
||||
{
|
||||
std::string blobName = baseBlobName + RandomString();
|
||||
auto blobClient = m_blobContainerClient->GetAppendBlobClient(blobName);
|
||||
EXPECT_NO_THROW(blobClient.Create());
|
||||
auto blobUrl = blobClient.GetUri();
|
||||
EXPECT_EQ(
|
||||
blobUrl,
|
||||
m_blobContainerClient->GetUri() + "/" + Storage::Details::UrlEncodePath(blobName));
|
||||
}
|
||||
{
|
||||
std::string blobName = baseBlobName + RandomString();
|
||||
auto blobClient = m_blobContainerClient->GetPageBlobClient(blobName);
|
||||
EXPECT_NO_THROW(blobClient.Create(1024));
|
||||
auto blobUrl = blobClient.GetUri();
|
||||
EXPECT_EQ(
|
||||
blobUrl,
|
||||
m_blobContainerClient->GetUri() + "/" + Storage::Details::UrlEncodePath(blobName));
|
||||
}
|
||||
{
|
||||
std::string blobName = baseBlobName + RandomString();
|
||||
auto blobClient = m_blobContainerClient->GetBlockBlobClient(blobName);
|
||||
EXPECT_NO_THROW(blobClient.UploadFrom(nullptr, 0));
|
||||
auto blobUrl = blobClient.GetUri();
|
||||
EXPECT_EQ(
|
||||
blobUrl,
|
||||
m_blobContainerClient->GetUri() + "/" + Storage::Details::UrlEncodePath(blobName));
|
||||
}
|
||||
}
|
||||
|
||||
}}} // namespace Azure::Storage::Test
|
||||
|
||||
@ -64,5 +64,6 @@ namespace Azure { namespace Storage {
|
||||
std::string Sha256(const std::string& text);
|
||||
std::string HmacSha256(const std::string& text, const std::string& key);
|
||||
std::string UrlEncodeQueryParameter(const std::string& value);
|
||||
std::string UrlEncodePath(const std::string& value);
|
||||
} // namespace Details
|
||||
}} // namespace Azure::Storage
|
||||
|
||||
@ -23,15 +23,16 @@
|
||||
namespace Azure { namespace Storage {
|
||||
|
||||
namespace Details {
|
||||
static const char* c_unreserved
|
||||
= "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._~";
|
||||
static const char* c_subdelimiters = "!$&'()*+,;=";
|
||||
const char* c_hex = "0123456789ABCDEF";
|
||||
|
||||
std::string UrlEncodeQueryParameter(const std::string& value)
|
||||
{
|
||||
static const char* unreserved
|
||||
= "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._~";
|
||||
static const char* subdelimiters = "!$&'()*+,;=";
|
||||
|
||||
const static std::vector<bool> shouldEncodeTable = []() {
|
||||
std::string queryCharacters
|
||||
= std::string(unreserved) + std::string(subdelimiters) + "%/:@?";
|
||||
= std::string(c_unreserved) + std::string(c_subdelimiters) + "%/:@?";
|
||||
|
||||
std::vector<bool> ret(256, true);
|
||||
for (char c : queryCharacters)
|
||||
@ -48,7 +49,40 @@ namespace Azure { namespace Storage {
|
||||
return ret;
|
||||
}();
|
||||
|
||||
const char* hex = "0123456789ABCDEF";
|
||||
std::string encoded;
|
||||
for (char c : value)
|
||||
{
|
||||
unsigned char uc = c;
|
||||
if (shouldEncodeTable[uc])
|
||||
{
|
||||
encoded += '%';
|
||||
encoded += c_hex[(uc >> 4) & 0x0f];
|
||||
encoded += c_hex[uc & 0x0f];
|
||||
}
|
||||
else
|
||||
{
|
||||
encoded += c;
|
||||
}
|
||||
}
|
||||
return encoded;
|
||||
}
|
||||
|
||||
std::string UrlEncodePath(const std::string& value)
|
||||
{
|
||||
const static std::vector<bool> shouldEncodeTable = []() {
|
||||
std::string pathCharacters
|
||||
= std::string(c_unreserved) + std::string(c_subdelimiters) + "%/:@";
|
||||
|
||||
std::vector<bool> ret(256, true);
|
||||
for (char c : pathCharacters)
|
||||
{
|
||||
ret[c] = false;
|
||||
}
|
||||
// we also encode % and +
|
||||
ret['%'] = true;
|
||||
ret['+'] = true;
|
||||
return ret;
|
||||
}();
|
||||
|
||||
std::string encoded;
|
||||
for (char c : value)
|
||||
@ -57,8 +91,8 @@ namespace Azure { namespace Storage {
|
||||
if (shouldEncodeTable[uc])
|
||||
{
|
||||
encoded += '%';
|
||||
encoded += hex[(uc >> 4) & 0x0f];
|
||||
encoded += hex[uc & 0x0f];
|
||||
encoded += c_hex[(uc >> 4) & 0x0f];
|
||||
encoded += c_hex[uc & 0x0f];
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
Loading…
Reference in New Issue
Block a user