From acc1ec0a1a1218594bb17a96beedc3aa928637f4 Mon Sep 17 00:00:00 2001 From: Oleksii Zubko Date: Thu, 20 Aug 2026 00:13:40 +0300 Subject: [PATCH] Keep commas unescaped in query parameters `UrlBuilder.appendQuery` escaped string values with `encodeURIComponent`, which turns a comma into `%2C`. The Data APIs use the comma as a list separator, so a call such as `InteractiveApi.getFeatures({ id: "id1,id2" })` asked for a single feature whose id contains a comma instead of for two features. Array values were already joined with a literal comma, so the two branches of the same method disagreed. The comma is a sub-delimiter and is valid unescaped in a query component, so restore it after encoding. Relates-To: HERESUP-89500 Signed-off-by: Oleksii Zubko --- @here/olp-sdk-dataservice-api/lib/RequestBuilder.ts | 13 ++++++++++--- .../test/RequestBuilder.test.ts | 11 +++++++++++ 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/@here/olp-sdk-dataservice-api/lib/RequestBuilder.ts b/@here/olp-sdk-dataservice-api/lib/RequestBuilder.ts index ba49f9e6..abe25b53 100644 --- a/@here/olp-sdk-dataservice-api/lib/RequestBuilder.ts +++ b/@here/olp-sdk-dataservice-api/lib/RequestBuilder.ts @@ -68,7 +68,10 @@ export class UrlBuilder { } else if (typeof value === "boolean") { url += `${value}`; } else if (typeof value === "string") { - url += encodeURIComponent(value); + // The comma is a valid sub-delimiter of a query component and is + // used by the Data APIs as a list separator, the same way as for + // the array values below. Keep it unescaped. + url += encodeURIComponent(value).replace(/%2C/g, ","); } else if (Array.isArray(value)) { const encodedValues: string[] = []; value.forEach((val: string | number) => { @@ -86,13 +89,17 @@ export class UrlBuilder { * @param url The base URL. * @param hasQuery Whether the base URL already contains query parameters. */ - constructor(public url: string, public hasQuery: boolean = false) {} + constructor( + public url: string, + public hasQuery: boolean = false + ) {} /** * Appends a query parameter to the URL, either using '&key=value' or '?key=value' * depending on the [[hasQuery]] parameter. * - * Escapes all strings using `encodeURIComponent`. + * Escapes all strings using `encodeURIComponent`, except for the comma, + * which is kept unescaped as a list separator. * * String arrays are concatenated using commas. * diff --git a/@here/olp-sdk-dataservice-api/test/RequestBuilder.test.ts b/@here/olp-sdk-dataservice-api/test/RequestBuilder.test.ts index 5558714b..af8191eb 100644 --- a/@here/olp-sdk-dataservice-api/test/RequestBuilder.test.ts +++ b/@here/olp-sdk-dataservice-api/test/RequestBuilder.test.ts @@ -58,6 +58,17 @@ describe("UrlBuilderTest", function () { expect(testUrlBuilder.hasQuery).to.be.equal(true); }); + it("Method appendQuery should appends parameters key, value with commas to the URL.", async function () { + const builderWithCommas = new UrlBuilder("test-url"); + const mockedUrl = "test-url?testKey=testValue,testValue2"; + + builderWithCommas.appendQuery("testKey", "testValue,testValue2"); + + assert.isDefined(builderWithCommas); + expect(builderWithCommas.url).to.be.equal(mockedUrl); + expect(builderWithCommas.hasQuery).to.be.equal(true); + }); + it("Method appendQuery should not appends parameters to the URL if value is undefined.", async function () { const testUrlBuilder2 = new UrlBuilder("test-url"); const mockedUrl = "test-url";