From 2fcb67907255771c89a246c3e7426e134accea66 Mon Sep 17 00:00:00 2001 From: Andrew Gaul Date: Sun, 10 Nov 2024 10:47:49 -0800 Subject: [PATCH] Check both Content-MD5 and x-ms-blob-content-md5 --- ChangeLog.md | 1 + src/blob/handlers/BlockBlobHandler.ts | 2 ++ tests/blob/apis/blob.test.ts | 30 +++++++++++++++++++++++++++ 3 files changed, 33 insertions(+) diff --git a/ChangeLog.md b/ChangeLog.md index 18bd2b7e7..167f01c02 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -13,6 +13,7 @@ Blob: - GetBlob on Archive tier blobs now fails as expected. - Fixed issue of download 0 size blob with range > 0 should have header "Content-Range: bytes \*/0" in returned error. (issue #2458) - Aligned behavior with Azure to ignore invalid range requests for blob downloads. (issue #2458) +- Consider both Content-MD5 and x-ms-blob-content-md5 when creating a blob. Table: diff --git a/src/blob/handlers/BlockBlobHandler.ts b/src/blob/handlers/BlockBlobHandler.ts index 84703faff..ec9b11a12 100644 --- a/src/blob/handlers/BlockBlobHandler.ts +++ b/src/blob/handlers/BlockBlobHandler.ts @@ -46,6 +46,7 @@ export default class BlockBlobHandler context.request!.getHeader("content-type") || "application/octet-stream"; const contentMD5 = context.request!.getHeader("content-md5") + || context.request!.getHeader("x-ms-blob-content-md5") ? options.blobHTTPHeaders.blobContentMD5 || context.request!.getHeader("content-md5") : undefined; @@ -182,6 +183,7 @@ export default class BlockBlobHandler // https://learn.microsoft.com/en-us/rest/api/storageservices/put-block // options.blobHTTPHeaders = options.blobHTTPHeaders || {}; const contentMD5 = context.request!.getHeader("content-md5") + || context.request!.getHeader("x-ms-blob-content-md5") ? options.transactionalContentMD5 || context.request!.getHeader("content-md5") : undefined; diff --git a/tests/blob/apis/blob.test.ts b/tests/blob/apis/blob.test.ts index dc0260466..6d6ccbdbe 100644 --- a/tests/blob/apis/blob.test.ts +++ b/tests/blob/apis/blob.test.ts @@ -18,6 +18,7 @@ import { getUniqueName, sleep } from "../../testutils"; +import CustomMD5PolicyFactory from "../RequestPolicy/CustomMD5PolicyFactory"; import RangePolicyFactory from "../RequestPolicy/RangePolicyFactory"; // Set true to enable debug log @@ -2527,6 +2528,35 @@ describe("BlobAPIs", () => { assert.deepStrictEqual(result, tags); }); + it("upload invalid x-ms-blob-content-md5 @loki @sql", async () => { + const pipeline = newPipeline( + new StorageSharedKeyCredential( + EMULATOR_ACCOUNT_NAME, + EMULATOR_ACCOUNT_KEY + ), + { + retryOptions: { maxTries: 1 }, + // Make sure socket is closed once the operation is done. + keepAliveOptions: { enable: false } + } + ); + pipeline.factories.unshift( + new CustomMD5PolicyFactory("invalid-md5") + ); + const serviceClient = new BlobServiceClient(baseURL, pipeline); + const containerClient = serviceClient.getContainerClient(containerName); + + const blobClient = containerClient.getBlockBlobClient(blobName); + try { + await blobClient.upload("hello", 5, { tier: "Hot" }); + assert.fail("Expected MD5 error"); + } catch (err) { + assert.deepStrictEqual((err as any).statusCode, 400); + assert.deepStrictEqual((err as any).code, 'InvalidOperation'); + assert.deepStrictEqual((err as any).details.errorCode, 'InvalidOperation'); + } + }); + it("Acquire Lease on Breaking Lease status, if LeaseId not match, throw LeaseIdMismatchWithLease error @loki @sql", async () => { // TODO: implement the case later });