Skip to content

Commit

Permalink
fix(rest): correctly resolve relative paths in REST requests
Browse files Browse the repository at this point in the history
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)
  • Loading branch information
jan-molak committed Sep 14, 2023
1 parent 61fc2bc commit 1bdf3eb
Show file tree
Hide file tree
Showing 2 changed files with 16 additions and 3 deletions.
10 changes: 9 additions & 1 deletion packages/rest/spec/screenplay/abilities/CallAnApi.spec.ts
Expand Up @@ -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', () => {
Expand Down
9 changes: 7 additions & 2 deletions packages/rest/src/screenplay/abilities/CallAnApi.ts
Expand Up @@ -133,7 +133,10 @@ export class CallAnApi extends Ability {
* provided when the {@apilink Ability|ability} to {@apilink CallAnApi} was instantiated.
*/
request(config: AxiosRequestConfig): Promise<AxiosResponse> {
return this.captureResponseOf(this.axiosInstance.request(config));
return this.captureResponseOf(this.axiosInstance.request({
...config,
url: this.resolveUrl(config),
}));
}

/**
Expand All @@ -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;
}

/**
Expand Down

0 comments on commit 1bdf3eb

Please sign in to comment.