diff --git a/.changeset/silly-cycles-clap.md b/.changeset/silly-cycles-clap.md new file mode 100644 index 0000000000..dc456728ed --- /dev/null +++ b/.changeset/silly-cycles-clap.md @@ -0,0 +1,5 @@ +--- +'astro': patch +--- + +Fixes an issue where redirects did not replace slugs when the target of the redirect rule was not a verbatim route in the project. diff --git a/packages/astro/src/core/redirects/helpers.ts b/packages/astro/src/core/redirects/helpers.ts index 697cb0fd89..c3683b76ce 100644 --- a/packages/astro/src/core/redirects/helpers.ts +++ b/packages/astro/src/core/redirects/helpers.ts @@ -20,7 +20,14 @@ export function redirectRouteGenerate(redirectRoute: RouteData, data: Params): s if (typeof routeData !== 'undefined') { return routeData?.generate(data) || routeData?.pathname || '/'; } else if (typeof route === 'string') { - return route; + // TODO: this logic is duplicated between here and manifest/create.ts + let target = route + for (const param of Object.keys(data)) { + const paramValue = data[param]! + target = target.replace(`[${param}]`, paramValue) + target = target.replace(`[...${param}]`, paramValue) + } + return target } else if (typeof route === 'undefined') { return '/'; } diff --git a/packages/astro/test/redirects.test.js b/packages/astro/test/redirects.test.js index 63a0931247..dcbc6c06a3 100644 --- a/packages/astro/test/redirects.test.js +++ b/packages/astro/test/redirects.test.js @@ -15,6 +15,13 @@ describe('Astro.redirect', () => { redirects: { '/api/redirect': '/test', '/external/redirect': 'https://example.com/', + // for example, the real file handling the target path may be called + // src/pages/not-verbatim/target1/[something-other-than-dynamic].astro + '/source/[dynamic]': '/not-verbatim/target1/[dynamic]', + // may be called src/pages/not-verbatim/target2/[abc]/[xyz].astro + '/source/[dynamic]/[route]': '/not-verbatim/target2/[dynamic]/[route]', + // may be called src/pages/not-verbatim/target3/[...rest].astro + '/source/[...spread]': '/not-verbatim/target3/[...spread]', }, }); await fixture.build(); @@ -68,6 +75,27 @@ describe('Astro.redirect', () => { const response = await app.render(request); expect(response.status).to.equal(308); }); + + it('Forwards params to the target path - single param', async () => { + const app = await fixture.loadTestAdapterApp(); + const request = new Request('http://example.com/source/x'); + const response = await app.render(request); + expect(response.headers.get("Location")).to.equal("/not-verbatim/target1/x"); + }); + + it('Forwards params to the target path - multiple params', async () => { + const app = await fixture.loadTestAdapterApp(); + const request = new Request('http://example.com/source/x/y'); + const response = await app.render(request); + expect(response.headers.get("Location")).to.equal("/not-verbatim/target2/x/y"); + }); + + it('Forwards params to the target path - spread param', async () => { + const app = await fixture.loadTestAdapterApp(); + const request = new Request('http://example.com/source/x/y/z'); + const response = await app.render(request); + expect(response.headers.get("Location")).to.equal("/not-verbatim/target3/x/y/z"); + }); }); });