diff --git a/sdk/storage/azure-storage-blobs/CHANGELOG.md b/sdk/storage/azure-storage-blobs/CHANGELOG.md index c54fac5ad..21d5b54db 100644 --- a/sdk/storage/azure-storage-blobs/CHANGELOG.md +++ b/sdk/storage/azure-storage-blobs/CHANGELOG.md @@ -18,6 +18,7 @@ - Fixed a bug where lease ID didn't work for `BlobContainerClient::GetAccessPolicy()`. - Fixed a bug where sequence number access conditions didn't work for page blob operations. - Fixed a bug where `BlobItemDetails::EncryptionKeySha256` was always null because it wasn't correctly parsed from xml. +- Fixed a bug where `BlockBlobClient::GetBlockList` threw exception if the blob is not committed. ### Other Changes diff --git a/sdk/storage/azure-storage-blobs/inc/azure/storage/blobs/protocol/blob_rest_client.hpp b/sdk/storage/azure-storage-blobs/inc/azure/storage/blobs/protocol/blob_rest_client.hpp index 218cba480..e4d8a8b52 100644 --- a/sdk/storage/azure-storage-blobs/inc/azure/storage/blobs/protocol/blob_rest_client.hpp +++ b/sdk/storage/azure-storage-blobs/inc/azure/storage/blobs/protocol/blob_rest_client.hpp @@ -1885,17 +1885,18 @@ namespace Azure { namespace Storage { namespace Blobs { struct GetBlockListResult final { /** - * The ETag contains a value that you can use to perform operations conditionally. + * The ETag contains a value that you can use to perform operations conditionally. Empty if + * the blob is not never committed. */ Azure::ETag ETag; /** * The date and time the container was last modified. Any operation that modifies the blob, * including an update of the metadata or properties, changes the last-modified time of the - * blob. + * blob. Invalid if the blob is never committed. */ Azure::DateTime LastModified; /** - * Size of the blob. + * Size of the blob. Invalid if the blob is never committed. */ int64_t BlobSize = 0; /** @@ -9403,10 +9404,23 @@ namespace Azure { namespace Storage { namespace Blobs { reinterpret_cast(httpResponseBody.data()), httpResponseBody.size()); response = GetBlockListResultFromXml(reader); } - response.ETag = Azure::ETag(httpResponse.GetHeaders().at("etag")); - response.LastModified = Azure::DateTime::Parse( - httpResponse.GetHeaders().at("last-modified"), Azure::DateTime::DateFormat::Rfc1123); - response.BlobSize = std::stoll(httpResponse.GetHeaders().at("x-ms-blob-content-length")); + auto etag__iterator = httpResponse.GetHeaders().find("etag"); + if (etag__iterator != httpResponse.GetHeaders().end()) + { + response.ETag = Azure::ETag(httpResponse.GetHeaders().at("etag")); + } + auto last_modified__iterator = httpResponse.GetHeaders().find("last-modified"); + if (last_modified__iterator != httpResponse.GetHeaders().end()) + { + response.LastModified = Azure::DateTime::Parse( + last_modified__iterator->second, Azure::DateTime::DateFormat::Rfc1123); + } + auto x_ms_blob_content_length__iterator + = httpResponse.GetHeaders().find("x-ms-blob-content-length"); + if (x_ms_blob_content_length__iterator != httpResponse.GetHeaders().end()) + { + response.BlobSize = std::stoll(x_ms_blob_content_length__iterator->second); + } return Azure::Response(std::move(response), std::move(pHttpResponse)); } diff --git a/sdk/storage/azure-storage-blobs/test/ut/block_blob_client_test.cpp b/sdk/storage/azure-storage-blobs/test/ut/block_blob_client_test.cpp index 2124f3967..8a508a617 100644 --- a/sdk/storage/azure-storage-blobs/test/ut/block_blob_client_test.cpp +++ b/sdk/storage/azure-storage-blobs/test/ut/block_blob_client_test.cpp @@ -1149,4 +1149,25 @@ namespace Azure { namespace Storage { namespace Test { EXPECT_NO_THROW(blobClient.SetAccessTier(Blobs::Models::AccessTier::Cool, options)); } + TEST_F(BlockBlobClientTest, UncommittedBlob) + { + const std::string blobName = RandomString(); + auto blobClient = m_blobContainerClient->GetBlockBlobClient(blobName); + + std::vector buffer(100); + Azure::Core::IO::MemoryBodyStream stream(buffer.data(), buffer.size()); + blobClient.StageBlock("YWJjZA==", stream); + + Blobs::GetBlockListOptions getBlockListOptions; + getBlockListOptions.ListType = Blobs::Models::BlockListType::All; + auto res = blobClient.GetBlockList(getBlockListOptions).Value; + EXPECT_FALSE(res.ETag.HasValue()); + EXPECT_EQ(res.BlobSize, 0); + EXPECT_TRUE(res.CommittedBlocks.empty()); + EXPECT_FALSE(res.UncommittedBlocks.empty()); + + auto blobItem = GetBlobItem(blobName, Blobs::Models::ListBlobsIncludeFlags::UncomittedBlobs); + EXPECT_EQ(blobItem.BlobSize, 0); + } + }}} // namespace Azure::Storage::Test