diff --git a/.changeset/fix-cross-domain-redirect-skip.md b/.changeset/fix-cross-domain-redirect-skip.md new file mode 100644 index 000000000..84eca3685 --- /dev/null +++ b/.changeset/fix-cross-domain-redirect-skip.md @@ -0,0 +1,5 @@ +--- +"@headstartwp/core": patch +--- + +Fix: shouldSkipRedirect incorrectly skipping cross-domain redirects when pathnames match. Fixes #941 diff --git a/packages/core/src/utils/__tests__/fetchRedirect.ts b/packages/core/src/utils/__tests__/fetchRedirect.ts index 2342180fd..9d138a9ce 100644 --- a/packages/core/src/utils/__tests__/fetchRedirect.ts +++ b/packages/core/src/utils/__tests__/fetchRedirect.ts @@ -51,4 +51,18 @@ describe('fetchRedirect', () => { global.fetch = originalFetch; }); + + it('handles cross-domain redirect with same pathname', async () => { + const result = await fetchRedirect('/recipe/my-recipe/', 'http://example.com/'); + + expect(result.location).toBe('https://www.external-domain.com/recipe/my-recipe/'); + expect(result.status).toBe(302); + }); + + it('handles cross-domain redirect with different pathname', async () => { + const result = await fetchRedirect('/old-recipe/', 'http://example.com/'); + + expect(result.location).toBe('https://www.external-domain.com/new-recipe/'); + expect(result.status).toBe(301); + }); }); diff --git a/packages/core/src/utils/fetchRedirect.ts b/packages/core/src/utils/fetchRedirect.ts index 60cd0cfe0..defdcd658 100644 --- a/packages/core/src/utils/fetchRedirect.ts +++ b/packages/core/src/utils/fetchRedirect.ts @@ -28,6 +28,11 @@ function shouldSkipRedirect(link: string, redirect: string, sourceUrl: string) { return true; } + // Cross-domain redirects should never be skipped + if (linkURL.host !== redirectURL.host) { + return false; + } + const linkParams = linkURL.searchParams; const redirectParams = redirectURL.searchParams; diff --git a/packages/core/test/server-handlers.ts b/packages/core/test/server-handlers.ts index c390b9211..aa2897fba 100644 --- a/packages/core/test/server-handlers.ts +++ b/packages/core/test/server-handlers.ts @@ -36,6 +36,16 @@ const handlers = [ return res(redirect('http://example.com/redirect-test-missing-slash', 301)); }), + // Cross-domain redirect with same pathname + rest.head('http://example.com/recipe/my-recipe/', (req, res) => { + return res(redirect('https://www.external-domain.com/recipe/my-recipe/', 302)); + }), + + // Cross-domain redirect with different pathname + rest.head('http://example.com/old-recipe/', (req, res) => { + return res(redirect('https://www.external-domain.com/new-recipe/', 301)); + }), + rest.get(/\/test-endpoint/, (req, res, ctx) => { return res(ctx.json({ ok: true })); }),