diff --git a/edge-runtime/lib/response.ts b/edge-runtime/lib/response.ts index 31bb7ead7b..fa000a3842 100644 --- a/edge-runtime/lib/response.ts +++ b/edge-runtime/lib/response.ts @@ -210,7 +210,7 @@ export const buildResponse = async ({ logger.withFields({ redirect_url: redirect }).debug('Redirect url is same as original url') return } - edgeResponse.headers.set('location', redirect) + edgeResponse.headers.set('location', relativizeURL(redirect, request.url)) } // Data requests shouldn't automatically redirect in the browser (they might be HTML pages): they're handled by the router diff --git a/edge-runtime/lib/util.test.ts b/edge-runtime/lib/util.test.ts index 99d3bf3d63..98646b58dc 100644 --- a/edge-runtime/lib/util.test.ts +++ b/edge-runtime/lib/util.test.ts @@ -1,5 +1,5 @@ import { assertEquals } from 'https://deno.land/std@0.175.0/testing/asserts.ts' -import { rewriteDataPath } from './util.ts' +import { relativizeURL, rewriteDataPath } from './util.ts' Deno.test('rewriteDataPath', async (t) => { await t.step('should rewrite a data url', async () => { @@ -37,3 +37,26 @@ Deno.test('rewriteDataPath', async (t) => { assertEquals(result, '/_next/data/build-id/target.json') }) }) + +Deno.test('relativizeURL', async (t) => { + await t.step('should relativize a URL when origin matches', async () => { + const url = 'https://example.com/pathname' + const base = 'https://example.com/' + const result = relativizeURL(url, base) + assertEquals(result, '/pathname') + }) + + await t.step('should NOT relativize a URL when origin does not match', async () => { + const url = 'https://example.com/pathname' + const base = 'https://not-example.com/' + const result = relativizeURL(url, base) + assertEquals(result, 'https://example.com/pathname') + }) + + await t.step('accepts relative URL strings and produce relative URL as output', async () => { + const url = '/pathname' + const base = 'https://example.com/' + const result = relativizeURL(url, base) + assertEquals(result, '/pathname') + }) +}) diff --git a/tests/integration/middleware.test.ts b/tests/integration/middleware.test.ts index 5e8e7a2812..04153c97de 100644 --- a/tests/integration/middleware.test.ts +++ b/tests/integration/middleware.test.ts @@ -130,7 +130,7 @@ for (const { expect(response.status).toBe(307) expect(response.headers.get('location'), 'added a location header').toBeTypeOf('string') expect( - new URL(response.headers.get('location') as string).pathname, + new URL(response.headers.get('location') as string, 'http://n').pathname, 'redirected to the correct path', ).toEqual('/other') expect(response.headers.get('x-runtime')).toEqual(expectedRuntime) @@ -154,7 +154,7 @@ for (const { expect(response.status).toBe(307) expect(response.headers.get('location'), 'added a location header').toBeTypeOf('string') expect( - new URL(response.headers.get('location') as string).pathname, + new URL(response.headers.get('location') as string, 'http://n').pathname, 'redirected to the correct path', ).toEqual('/other') expect(response.headers.get('x-header-from-redirect'), 'hello').toBe('hello') @@ -357,7 +357,7 @@ for (const { expect(response.status).toBe(307) expect(response.headers.get('location'), 'added a location header').toBeTypeOf('string') expect( - new URL(response.headers.get('location') as string).pathname, + new URL(response.headers.get('location') as string, 'http://n').pathname, 'redirected to the correct path', ).toEqual('/other') expect(response.headers.get('x-header-from-redirect'), 'hello').toBe('hello') @@ -382,7 +382,7 @@ for (const { expect(response.status).toBe(307) expect(response.headers.get('location'), 'added a location header').toBeTypeOf('string') expect( - new URL(response.headers.get('location') as string).pathname, + new URL(response.headers.get('location') as string, 'http://n').pathname, 'redirected to the correct path', ).toEqual('/other') expect(response.headers.get('x-header-from-redirect'), 'hello').toBe('hello')