diff --git a/.changeset/nervous-chicken-allow.md b/.changeset/nervous-chicken-allow.md new file mode 100644 index 000000000000..214bd306ff4f --- /dev/null +++ b/.changeset/nervous-chicken-allow.md @@ -0,0 +1,5 @@ +--- +'@astrojs/vercel': patch +--- + +Fixes an issue where redirects did not work with the static adapter. diff --git a/packages/astro/src/core/logger/core.ts b/packages/astro/src/core/logger/core.ts index b3f3b725673e..db571d8f14da 100644 --- a/packages/astro/src/core/logger/core.ts +++ b/packages/astro/src/core/logger/core.ts @@ -26,6 +26,7 @@ export type LoggerLabel = | 'watch' | 'middleware' | 'preferences' + | 'redirects' // SKIP_FORMAT: A special label that tells the logger not to apply any formatting. // Useful for messages that are already formatted, like the server start message. | 'SKIP_FORMAT'; diff --git a/packages/astro/src/core/routing/manifest/create.ts b/packages/astro/src/core/routing/manifest/create.ts index c9c0bb071685..66f4a74fac39 100644 --- a/packages/astro/src/core/routing/manifest/create.ts +++ b/packages/astro/src/core/routing/manifest/create.ts @@ -451,6 +451,19 @@ export function createRouteManifest( .map(([{ dynamic, content }]) => (dynamic ? `[${content}]` : content)) .join('/')}`.toLowerCase(); + { + let destination: string + if (typeof to === "string") { + destination = to + } + else { + destination = to.destination + } + if (/^https?:\/\//.test(destination)) { + logger.warn('redirects', `Redirecting to an external URL is not officially supported: ${from} -> ${to}`); + } + } + const routeData: RouteData = { type: 'redirect', route, diff --git a/packages/astro/test/redirects.test.js b/packages/astro/test/redirects.test.js index bf9ad15f56f3..63a09312478f 100644 --- a/packages/astro/test/redirects.test.js +++ b/packages/astro/test/redirects.test.js @@ -14,6 +14,7 @@ describe('Astro.redirect', () => { adapter: testAdapter(), redirects: { '/api/redirect': '/test', + '/external/redirect': 'https://example.com/', }, }); await fixture.build(); @@ -27,6 +28,15 @@ describe('Astro.redirect', () => { expect(response.headers.get('location')).to.equal('/login'); }); + // ref: https://github.com/withastro/astro/pull/9287 + it.skip('Ignores external redirect', async () => { + const app = await fixture.loadTestAdapterApp(); + const request = new Request('http://example.com/external/redirect'); + const response = await app.render(request); + expect(response.status).to.equal(404); + expect(response.headers.get('location')).to.equal(null); + }); + it('Warns when used inside a component', async () => { const app = await fixture.loadTestAdapterApp(); const request = new Request('http://example.com/late'); diff --git a/packages/integrations/vercel/src/lib/redirects.ts b/packages/integrations/vercel/src/lib/redirects.ts index 8613be2ed72d..7aec1cf3b0b9 100644 --- a/packages/integrations/vercel/src/lib/redirects.ts +++ b/packages/integrations/vercel/src/lib/redirects.ts @@ -21,8 +21,7 @@ function getMatchPattern(segments: RoutePart[][]) { .map((segment) => { return segment[0].spread ? '(?:\\/(.*?))?' - : '\\/' + - segment + : segment .map((part) => { if (part) return part.dynamic diff --git a/packages/integrations/vercel/test/redirects.test.js b/packages/integrations/vercel/test/redirects.test.js index df17664eec6e..9b6a9d50d828 100644 --- a/packages/integrations/vercel/test/redirects.test.js +++ b/packages/integrations/vercel/test/redirects.test.js @@ -32,15 +32,15 @@ describe('Redirects', () => { it('define static routes', async () => { const config = await getConfig(); - const oneRoute = config.routes.find((r) => r.src === '/\\/one'); + const oneRoute = config.routes.find((r) => r.src === '/one'); expect(oneRoute.headers.Location).to.equal('/'); expect(oneRoute.status).to.equal(301); - const twoRoute = config.routes.find((r) => r.src === '/\\/two'); + const twoRoute = config.routes.find((r) => r.src === '/two'); expect(twoRoute.headers.Location).to.equal('/'); expect(twoRoute.status).to.equal(301); - const threeRoute = config.routes.find((r) => r.src === '/\\/three'); + const threeRoute = config.routes.find((r) => r.src === '/three'); expect(threeRoute.headers.Location).to.equal('/'); expect(threeRoute.status).to.equal(302); }); @@ -48,7 +48,7 @@ describe('Redirects', () => { it('defines dynamic routes', async () => { const config = await getConfig(); - const blogRoute = config.routes.find((r) => r.src.startsWith('/\\/blog')); + const blogRoute = config.routes.find((r) => r.src.startsWith('/blog')); expect(blogRoute).to.not.be.undefined; expect(blogRoute.headers.Location.startsWith('/team/articles')).to.equal(true); expect(blogRoute.status).to.equal(301); @@ -57,7 +57,7 @@ describe('Redirects', () => { it('define trailingSlash redirect for sub pages', async () => { const config = await getConfig(); - const subpathRoute = config.routes.find((r) => r.src === '/\\/subpage'); + const subpathRoute = config.routes.find((r) => r.src === '/subpage'); expect(subpathRoute).to.not.be.undefined; expect(subpathRoute.headers.Location).to.equal('/subpage/'); });