diff --git a/src/lib/__tests__/api-url.test.ts b/src/lib/__tests__/api-url.test.ts index 2844e2522..1415c80f7 100644 --- a/src/lib/__tests__/api-url.test.ts +++ b/src/lib/__tests__/api-url.test.ts @@ -11,19 +11,19 @@ test('uses basePath with the default api path', () => { ); }); -test('uses a relative API_URL', () => { +test('routes calls through a relative API_URL', () => { expect(getApiUrl('/websites', { apiUrl: '/backend/api', basePath: '' })).toBe( '/backend/api/websites', ); }); -test('uses basePath with a relative API_URL', () => { +test('routes calls through basePath with a relative API_URL', () => { expect(getApiUrl('/websites', { apiUrl: '/backend/api', basePath: '/analytics' })).toBe( '/analytics/backend/api/websites', ); }); -test('uses an absolute API_URL directly', () => { +test('routes calls through an absolute API_URL', () => { expect(getApiUrl('/websites', { apiUrl: 'https://api.example.com/api', basePath: '' })).toBe( 'https://api.example.com/api/websites', ); @@ -34,3 +34,24 @@ test('leaves absolute request URLs unchanged', () => { 'https://example.com/custom', ); }); + +test('keeps /auth/* on the default api path', () => { + expect( + getApiUrl('/auth/login', { apiUrl: 'https://api.example.com/api', basePath: '' }), + ).toBe('/api/auth/login'); +}); + +test('keeps /config on the default api path', () => { + expect(getApiUrl('/config', { apiUrl: 'https://api.example.com/api', basePath: '' })).toBe( + '/api/config', + ); +}); + +test('keeps /auth/* on the default api path with basePath', () => { + expect( + getApiUrl('/auth/verify', { + apiUrl: 'https://api.example.com/api', + basePath: '/analytics', + }), + ).toBe('/analytics/api/auth/verify'); +}); diff --git a/src/lib/api-url.ts b/src/lib/api-url.ts index 765c730b0..104634fde 100644 --- a/src/lib/api-url.ts +++ b/src/lib/api-url.ts @@ -3,6 +3,11 @@ type ApiUrlOptions = { basePath?: string; }; +const APP_ROUTE_PATTERNS: RegExp[] = [ + /^\/auth(\/|$)/, + /^\/config(\/|$)/, +]; + function trimTrailingSlash(value: string) { return value.replace(/\/+$/, ''); } @@ -23,13 +28,19 @@ function isAbsoluteUrl(url: string) { return /^https?:\/\//i.test(url); } +function isAppRoute(url: string) { + const path = `/${trimLeadingSlash(url.split('?')[0])}`; + return APP_ROUTE_PATTERNS.some(re => re.test(path)); +} + export function getApiUrl(url: string, options: ApiUrlOptions = {}) { if (isAbsoluteUrl(url)) { return url; } const { apiUrl = process.env.apiUrl || '', basePath = process.env.basePath || '' } = options; - const baseUrl = apiUrl + const useApiUrl = apiUrl && !isAppRoute(url); + const baseUrl = useApiUrl ? isAbsoluteUrl(apiUrl) ? apiUrl : joinPath(basePath, apiUrl)