From 1bdf3eb05701007c8d640e4529f701862f223480 Mon Sep 17 00:00:00 2001 From: Jan Molak <1089173+jan-molak@users.noreply.github.com> Date: Thu, 14 Sep 2023 23:44:34 +0100 Subject: [PATCH] fix(rest): correctly resolve relative paths in REST requests Axios seems to have a bug that manifests itself when the baseURL is defined with a path, e.g. https://example.org/api/v1 Then, when an individual request is supposed to be sent to an absolute path, e.g. /secure/oauth, Axios incorrectly resolves this combination as https://example.org/api/v1/secure/oauth instead of https://example.org/secure/oauth This change fixes this behaviour by relying on Nodejs built-in URL resolution: new URL(path, baseURL) --- .../rest/spec/screenplay/abilities/CallAnApi.spec.ts | 10 +++++++++- packages/rest/src/screenplay/abilities/CallAnApi.ts | 9 +++++++-- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/packages/rest/spec/screenplay/abilities/CallAnApi.spec.ts b/packages/rest/spec/screenplay/abilities/CallAnApi.spec.ts index 53985a22885..050bf4801c0 100644 --- a/packages/rest/spec/screenplay/abilities/CallAnApi.spec.ts +++ b/packages/rest/spec/screenplay/abilities/CallAnApi.spec.ts @@ -75,11 +75,19 @@ describe('CallAnApi', () => { it('provides a way to determine the actual target URL the request will be sent to', () => { const callaAnApi = CallAnApi.at('https://example.org/api/v4'); - const actualUrl = callaAnApi.resolveUrl({ url: 'products/3' }); + const actualUrl = callaAnApi.resolveUrl({ baseURL: 'https://example.org/api/v4/', url: 'products/3' }); expect(actualUrl).to.equal('https://example.org/api/v4/products/3') }); + it('correctly resolves absolute URL paths', () => { + const callaAnApi = CallAnApi.at('https://example.org/api/v4'); + + const actualUrl = callaAnApi.resolveUrl({ baseURL: 'https://example.org/api/v4/', url: '/api/v5/products/3' }); + + expect(actualUrl).to.equal('https://example.org/api/v5/products/3') + }); + describe('when dealing with errors', () => { it('complains if you try to retrieve the last response before making an API call', () => { diff --git a/packages/rest/src/screenplay/abilities/CallAnApi.ts b/packages/rest/src/screenplay/abilities/CallAnApi.ts index eaf9d63d74d..151f3858a7d 100644 --- a/packages/rest/src/screenplay/abilities/CallAnApi.ts +++ b/packages/rest/src/screenplay/abilities/CallAnApi.ts @@ -133,7 +133,10 @@ export class CallAnApi extends Ability { * provided when the {@apilink Ability|ability} to {@apilink CallAnApi} was instantiated. */ request(config: AxiosRequestConfig): Promise { - return this.captureResponseOf(this.axiosInstance.request(config)); + return this.captureResponseOf(this.axiosInstance.request({ + ...config, + url: this.resolveUrl(config), + })); } /** @@ -147,7 +150,9 @@ export class CallAnApi extends Ability { * @param config */ resolveUrl(config: AxiosRequestConfig): string { - return this.axiosInstance.getUri(config); + return config.baseURL + ? new URL(config.url, config.baseURL).toString() + : config.url; } /**