From 59a059cf11282ce8ac9fa2f2f6be9ce94ea7844d Mon Sep 17 00:00:00 2001 From: Emma Zhu Date: Thu, 7 Aug 2025 09:53:12 +0800 Subject: [PATCH] Change character validation in tag key to align with server behavior --- ChangeLog.md | 4 +++ .../QueryInterpreter/QueryParser.ts | 35 +++++++------------ tests/blob/apis/blob.test.ts | 13 +++++++ 3 files changed, 30 insertions(+), 22 deletions(-) diff --git a/ChangeLog.md b/ChangeLog.md index b45b3a41b..4834bdfe5 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -4,6 +4,10 @@ ## Upcoming Release +Blob: + +- Changed charaters validation against tag key in filtering blobs with tags to align with service side behavior. (issue #2561) + ## 2025.07 Version 3.35.0 General: diff --git a/src/blob/persistence/QueryInterpreter/QueryParser.ts b/src/blob/persistence/QueryInterpreter/QueryParser.ts index 3b03b9406..322bb3838 100644 --- a/src/blob/persistence/QueryInterpreter/QueryParser.ts +++ b/src/blob/persistence/QueryInterpreter/QueryParser.ts @@ -314,16 +314,23 @@ class QueryParser { this.query.throw('expecting tag value'); } - private ContainsInvalidTagKeyCharacter(key: string): boolean { + private validateTagCharacter(key: string) { for (let c of key) { if (!(c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' || c >= '0' && c <= '9' || - c == '_')) { - return true; + c == ' ' || + c == '+' || + c == '-' || + c == '.' || + c == '/' || + c == ':' || + c == '=' || + c == '_' + )) { + this.query.throw(`'${c}' not permitted in tag name or value`); } } - return false; } private validateKey(key: string) { @@ -342,30 +349,14 @@ class QueryParser { if (!this.conditionHeader && ((key.length == 0) || (key.length > 128))) { this.query.throw('tag must be between 1 and 128 characters in length'); } - if (this.ContainsInvalidTagKeyCharacter(key)) { - this.query.throw(`unexpected '${key}'`); - } + this.validateTagCharacter(key); } private validateValue(value: string) { if (!this.conditionHeader && (value.length > 256)) { this.query.throw(`tag value must be between 0 and 256 characters in length`); } - for (let c of value) { - if (!(c >= 'a' && c <= 'z' || - c >= 'A' && c <= 'Z' || - c >= '0' && c <= '9' || - c == ' ' || - c == '+' || - c == '-' || - c == '.' || - c == '/' || - c == ':' || - c == '=' || - c == '_')) { - this.query.throw(`'${c}' not permitted in tag name or value`); - } - } + this.validateTagCharacter(value); } /** diff --git a/tests/blob/apis/blob.test.ts b/tests/blob/apis/blob.test.ts index 141ff1c36..4f4e33153 100644 --- a/tests/blob/apis/blob.test.ts +++ b/tests/blob/apis/blob.test.ts @@ -2434,6 +2434,19 @@ describe("BlobAPIs", () => { assert.deepStrictEqual(outputTags1, tags); }); + it("get blob tag with ifTags condition - key with special chars @loki @sql", async () => { + let tags: Tags = { + " key 1 +-.:=_/": '1a', + key2: 'a1' + }; + await blobClient.setTags(tags); + + let queryString = `" key 1 +-.:=_/"='1a'`; + let outputTags = (await blobClient.getTags({ conditions: { tagConditions: queryString } })).tags; + assert.deepStrictEqual(outputTags, tags); + }); + + it("get blob tag with long ifTags condition @loki @sql", async () => { const tags = { tag1: "val1",