[BUG] Inconsistent ETag results in Storage Blob SDK GetPropertiesAsync and GetBlobsAsync and ETag documentation issue
See original GitHub issueLibrary name and version
Azure.Storage.Blobs 12.13.0
Describe the bug
Hi Azure SDK Team.
I noticed some inconsistent ETag documentation and corresponding inconsistent behavior of ETag usage in at least two Azure Blob Storage APIs. I initially thought it would be two issues, but I think they are so related enough to be included in this one. Hope that is fine for you and does not produce any tracking issues.
Let me start with the documentation of the ToString
method in the official documentation:
https://docs.microsoft.com/de-de/dotnet/api/azure.etag.tostring?view=azure-dotnet#azure-etag-tostring(system-string)
The following example is provided:
ETag tag = ETag.Parse("\"sometag\"");
Console.WriteLine(tag.ToString("G"));
// Displays: sometag
Console.WriteLine(tag.ToString("H"));
// Displays: "sometag"
This example cannot be used by external code, because the Parse
method is internal. If I now use similar code, but initialize the Etag with the constructor that is public, the results will be wrong:
ETag tag = new ETag("\"sometag\"");
Console.WriteLine(tag.ToString("G"));
// Displays: "sometag"
Console.WriteLine(tag.ToString("H"));
// Displays: "sometag"
The results are wrong because the Parse
method does trim the quotes during initialization, the constructor does not. For anyone using the API from the outside, this behavior is not obvious and lead to bugs in our code and possibly the inconsistent behavior of the two sdk methods provided in the reproduction steps.
Expected behavior
It would be a good thing to either make the ETag.Parse
method publicly available, change the documentation to be more clear about quote behavior, or have the constructor behave the same way as the method.
I guess making the constructor behavior similiar could also immediately resolve the problem with creation of ETags, but is considerably more breaking.
Also, BlobClient.GetPropertiesAsync
and BlobContainerClient.GetBlobsAsync
should produce a consistent behavior of ETag formats.
Actual behavior
ETag.Parse
is not public, and using the constructor results in a different behavior than stated in the documentation
BlobClient.GetPropertiesAsync
and BlobContainerClient.GetBlobsAsync
property results produce different ETag formats for the same Blob when formatted with ToString
.
I noticed this behavior after updating from 12.10.0 to 12.13.0, which broke quite a few of our tests that assert on the ETags. This would have resulted in wrong ETag comparison behavior if it had slipped into production.
We currently work around it by always trimming all outer quotes from ETags whenever we load them from blob storage. This solution only works as long as we do not use Weak ETags.
Reproduction Steps
The two different ways of creating an ETag probably lead to the following inconsistent behavior of Storage SDK Methods BlobClient.GetPropertiesAsync
and BlobContainerClient.GetBlobsAsync
. If you fetch a Blob’s metadata using these two different approaches:
// fetching metadata for the single blob
props1 = await blobClient.GetPropertiesAsync(conditions: null, cancellationToken);
var etag1 = props1.ETag.ToString("G"); // produces "\"0xabcd1234\""
// fetching metadata for the blob as part of a batch
var blobs = _blobContainerClient.GetBlobsAsync(
prefix: blobPrefix,
traits: BlobTraits.Metadata,
cancellationToken: cancellationToken);
await foreach (var blob in blobs.WithCancellation(cancellationToken))
{
var etag2 = blob.Properties.ETag!.Value.ToString("G") // produces "0xabcd1234"
}
The blob ETag format is different, and a comparison of the two ETags ToString
Calls would result in non-comparable data.
Environment
- .NET 6.0.7 on Windows
- IDE: VS Prof. 17.2.5
Issue Analytics
- State:
- Created a year ago
- Comments:6 (3 by maintainers)
Top GitHub Comments
Unfortunately we would have to wait till something like version 13+ of the SDK (as of now we’re only doing v12.XX releases which do not allow breaking changes). We will consider this issue in the future, though we also have to consider the customers who would also be upset by the difference in the change, but that’s obviously up for future discussion.
We will look to updating the documentation for how the ETag value will come back with the quotations or not since this is a common issue.
Thank you, sorry that my initial research did not find the above mentioned issue. But even if it is a breaking change, wouldn’t it be possible to update the behavior in a future major release, with deprecation or other notices up front? Or at least update the documentation to mention this flaw. The way it is now is very error-prone to use.