diff --git a/src/lib/http.test.ts b/src/lib/http.test.ts index 28596b4..9745fe9 100644 --- a/src/lib/http.test.ts +++ b/src/lib/http.test.ts @@ -681,6 +681,26 @@ describe('HttpClient — Dynatrace authentication', () => { await client.dynatracePlatform('/platform/storage/query/v1/query:execute'); expect(authorization).toBe('Bearer platform-token'); }); + + it('preserves /e/ path segment for Dynatrace Managed base URLs', async () => { + const capturedUrls: string[] = []; + vi.stubGlobal('fetch', async (url: string) => { + capturedUrls.push(url); + return new Response('{"entities":[],"totalCount":0}', { status: 200 }); + }); + const client = new HttpClient(baseConfig({ + dynatrace: { + baseUrl: 'https://apm.pncint.net/e/ccd497ef-cb0f-4294-9044-1b6faead0768', + apiToken: 'tok', + platformUrl: undefined, + platformToken: undefined + } + })); + await client.dynatrace('/api/v2/entities'); + expect(capturedUrls[0]).toBe( + 'https://apm.pncint.net/e/ccd497ef-cb0f-4294-9044-1b6faead0768/api/v2/entities' + ); + }); }); describe('HttpClient — --debug mode', () => { diff --git a/src/lib/http.ts b/src/lib/http.ts index c7a8ebd..962c15c 100644 --- a/src/lib/http.ts +++ b/src/lib/http.ts @@ -41,7 +41,14 @@ function redactHeaders(headers: RequestInit['headers']): Record } function buildUrl(base: string, path: string, params?: Record): string { - const url = new URL(path, base.endsWith('/') ? base : base + '/'); + const normalizedBase = base.endsWith('/') ? base : base + '/'; + // Strip a leading '/' so that new URL(path, base) resolves relative to base's full + // path rather than the origin. Per the WHATWG URL spec, an absolute-path reference + // (starting with '/') resolves against the origin and discards any path already + // present in base — which silently drops path segments like '/e/' + // from Dynatrace Managed or Artifactory-with-context-root base URLs. + const normalizedPath = path.startsWith('/') ? path.slice(1) : path; + const url = new URL(normalizedPath, normalizedBase); if (params) { for (const [key, val] of Object.entries(params)) { if (val !== undefined) {