From 1161c7be64e8381be4b859e0548f3d6d7f49c608 Mon Sep 17 00:00:00 2001 From: Michael Solomon Date: Tue, 10 Sep 2024 14:25:45 +0300 Subject: [PATCH] fix(fetch): rebase relative redirect URL against `request.url` (#628) --- src/interceptors/fetch/utils/followRedirect.ts | 3 ++- .../compliance/fetch-follow-redirects.test.ts | 15 +++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/src/interceptors/fetch/utils/followRedirect.ts b/src/interceptors/fetch/utils/followRedirect.ts index e577d57b..bd76e63b 100644 --- a/src/interceptors/fetch/utils/followRedirect.ts +++ b/src/interceptors/fetch/utils/followRedirect.ts @@ -25,7 +25,8 @@ export async function followFetchRedirect( let locationUrl: URL try { - locationUrl = new URL(response.headers.get('location')!) + // If the location is a relative URL, use the request URL as the base URL. + locationUrl = new URL(response.headers.get('location')!, request.url) } catch (error) { return Promise.reject(createNetworkError(error)) } diff --git a/test/modules/fetch/compliance/fetch-follow-redirects.test.ts b/test/modules/fetch/compliance/fetch-follow-redirects.test.ts index cc3bc4ff..e6b9b2c8 100644 --- a/test/modules/fetch/compliance/fetch-follow-redirects.test.ts +++ b/test/modules/fetch/compliance/fetch-follow-redirects.test.ts @@ -48,6 +48,21 @@ it('follows a mocked redirect to the original server', async () => { await expect(response.text()).resolves.toBe('redirected') }) +it('follows a mocked relative redirect to the original server', async () => { + interceptor.on('request', ({ request, controller }) => { + if (request.url.endsWith('/original')) { + return controller.respondWith( + new Response(null, { status: 302, headers: { location: '/redirected' } }) + ) + } + }) + + const response = await fetch(httpServer.http.url('/original')) + + expect(response.status).toBe(200) + await expect(response.text()).resolves.toBe('redirected') +}) + it('follows a mocked redirect to a mocked response', async () => { interceptor.on('request', ({ request, controller }) => { if (request.url.endsWith('/original')) {