diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 55d4ebb..0ad5f79 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -9,8 +9,7 @@ jobs: linux-tests: strategy: matrix: - # TODO: remove older node versions - node: [10, 12, 14, 16, 18, 20, 22] + node: [20, 22] fail-fast: false runs-on: ubuntu-latest steps: diff --git a/CHANGELOG.md b/CHANGELOG.md index 29de855..d808947 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,8 @@ # CHANGELOG +## 2.0.0 +* Path parameter special characters are encoded by default + ## 1.8.0 * Make request `body` for HTTP endpoint calls optional [#117](https://github.com/SalesforceCommerceCloud/commerce-sdk-core/pull/117/files) diff --git a/src/base/resource.ts b/src/base/resource.ts index 0eacb37..25501a8 100644 --- a/src/base/resource.ts +++ b/src/base/resource.ts @@ -41,9 +41,21 @@ export class Resource { * @returns Path with actual parameters */ substitutePathParameters(path = "", parameters: PathParameters = {}): string { + const encodedPathParams: PathParameters = {}; + + Object.keys(parameters || {}).forEach((key) => { + const value = parameters?.[key]; + if (value) { + encodedPathParams[key] = encodeURIComponent(value); + } + }); + return path.replace(/\{([^}]+)\}/g, (_entireMatch, param) => { - if (parameters.hasOwnProperty(param) && parameters[param] !== undefined) { - return parameters[param]; + if ( + encodedPathParams.hasOwnProperty(param) && + encodedPathParams[param] !== undefined + ) { + return encodedPathParams[param]; } throw new Error( `Failed to find a value for required path parameter '${param}'` diff --git a/src/base/staticClient.ts b/src/base/staticClient.ts index b2333bc..091cbff 100644 --- a/src/base/staticClient.ts +++ b/src/base/staticClient.ts @@ -263,9 +263,7 @@ export async function _delete(options: SdkFetchOptions): Promise { * @returns Either the Response object or the DTO inside it wrapped in a promise, * depending upon options.rawResponse */ -export async function _patch( - options: SdkFetchOptions -): Promise { +export async function _patch(options: SdkFetchOptions): Promise { return runFetch("patch", options); } diff --git a/test/resource.test.ts b/test/resource.test.ts index 6d75bd4..a32d543 100644 --- a/test/resource.test.ts +++ b/test/resource.test.ts @@ -200,4 +200,13 @@ describe("Resource class tests", () => { // URI decoded: baseUri/path?expand=availability,images&refine=price=(0..150)&refine=c_refinementColor=Red ); }); + + it("returns correct url with path param with special characters", () => { + assert.strictEqual( + new Resource("https://example.com", {}, "/path/with/{special}/chars", { + special: "test!@#$%", + }).toString(), + "https://example.com/path/with/test!%40%23%24%25/chars" + ); + }); });