diff --git a/.changeset/famous-numbers-smell.md b/.changeset/famous-numbers-smell.md
new file mode 100644
index 000000000..be778992a
--- /dev/null
+++ b/.changeset/famous-numbers-smell.md
@@ -0,0 +1,5 @@
+---
+'astro': patch
+---
+
+Fixed an issue where configured redirects with dynamic routes did not work in dev mode.
diff --git a/packages/astro/src/core/render/params-and-props.ts b/packages/astro/src/core/render/params-and-props.ts
index 6cdb05ed1..8c75e75e2 100644
--- a/packages/astro/src/core/render/params-and-props.ts
+++ b/packages/astro/src/core/render/params-and-props.ts
@@ -1,6 +1,7 @@
import type { ComponentInstance, Params, Props, RouteData } from '../../@types/astro.js';
import { AstroError, AstroErrorData } from '../errors/index.js';
import type { Logger } from '../logger/core.js';
+import { routeIsRedirect } from '../redirects/index.js';
import { getParams } from '../routing/params.js';
import { RouteCache, callGetStaticPaths, findPathItemByKey } from './route-cache.js';
@@ -25,6 +26,10 @@ export async function getParamsAndProps(opts: GetParamsAndPropsOptions): Promise
// This is a dynamic route, start getting the params
const params = getRouteParams(route, pathname) ?? {};
+ if (routeIsRedirect(route)) {
+ return [params, {}]
+ }
+
validatePrerenderEndpointCollision(route, mod, params);
// During build, the route cache should already be populated.
diff --git a/packages/astro/test/fixtures/ssr-redirect/package.json b/packages/astro/test/fixtures/redirects/package.json
similarity index 100%
rename from packages/astro/test/fixtures/ssr-redirect/package.json
rename to packages/astro/test/fixtures/redirects/package.json
diff --git a/packages/astro/test/fixtures/ssr-redirect/src/components/redirect.astro b/packages/astro/test/fixtures/redirects/src/components/redirect.astro
similarity index 100%
rename from packages/astro/test/fixtures/ssr-redirect/src/components/redirect.astro
rename to packages/astro/test/fixtures/redirects/src/components/redirect.astro
diff --git a/packages/astro/test/fixtures/ssr-redirect/src/middleware.ts b/packages/astro/test/fixtures/redirects/src/middleware.ts
similarity index 100%
rename from packages/astro/test/fixtures/ssr-redirect/src/middleware.ts
rename to packages/astro/test/fixtures/redirects/src/middleware.ts
diff --git a/packages/astro/test/fixtures/ssr-redirect/src/pages/articles/[...slug].astro b/packages/astro/test/fixtures/redirects/src/pages/articles/[...slug].astro
similarity index 100%
rename from packages/astro/test/fixtures/ssr-redirect/src/pages/articles/[...slug].astro
rename to packages/astro/test/fixtures/redirects/src/pages/articles/[...slug].astro
diff --git a/packages/astro/test/fixtures/ssr-redirect/src/pages/late.astro b/packages/astro/test/fixtures/redirects/src/pages/late.astro
similarity index 100%
rename from packages/astro/test/fixtures/ssr-redirect/src/pages/late.astro
rename to packages/astro/test/fixtures/redirects/src/pages/late.astro
diff --git a/packages/astro/test/fixtures/ssr-redirect/src/pages/middleware-redirect.astro b/packages/astro/test/fixtures/redirects/src/pages/middleware-redirect.astro
similarity index 100%
rename from packages/astro/test/fixtures/ssr-redirect/src/pages/middleware-redirect.astro
rename to packages/astro/test/fixtures/redirects/src/pages/middleware-redirect.astro
diff --git a/packages/astro/test/fixtures/redirects/src/pages/more/[dynamic].astro b/packages/astro/test/fixtures/redirects/src/pages/more/[dynamic].astro
new file mode 100644
index 000000000..f980c25ba
--- /dev/null
+++ b/packages/astro/test/fixtures/redirects/src/pages/more/[dynamic].astro
@@ -0,0 +1,8 @@
+---
+export function getStaticPaths() {
+ return [{ params: { dynamic:'hello' } }]
+}
+---
+{JSON.stringify(Astro.params)}
+
+home
\ No newline at end of file
diff --git a/packages/astro/test/fixtures/redirects/src/pages/more/[dynamic]/[route].astro b/packages/astro/test/fixtures/redirects/src/pages/more/[dynamic]/[route].astro
new file mode 100644
index 000000000..94ccb545f
--- /dev/null
+++ b/packages/astro/test/fixtures/redirects/src/pages/more/[dynamic]/[route].astro
@@ -0,0 +1,8 @@
+---
+export function getStaticPaths() {
+ return [{ params: { dynamic:'hello', route:'world' } }]
+}
+---
+{JSON.stringify(Astro.params)}
+
+home
diff --git a/packages/astro/test/fixtures/redirects/src/pages/more/new/[...spread].astro b/packages/astro/test/fixtures/redirects/src/pages/more/new/[...spread].astro
new file mode 100644
index 000000000..f34bb28f6
--- /dev/null
+++ b/packages/astro/test/fixtures/redirects/src/pages/more/new/[...spread].astro
@@ -0,0 +1,8 @@
+---
+export function getStaticPaths() {
+ return [{ params: {spread:'welcome/world'} }]
+}
+---
+{JSON.stringify(Astro.params)}
+
+home
\ No newline at end of file
diff --git a/packages/astro/test/fixtures/ssr-redirect/src/pages/secret.astro b/packages/astro/test/fixtures/redirects/src/pages/secret.astro
similarity index 100%
rename from packages/astro/test/fixtures/ssr-redirect/src/pages/secret.astro
rename to packages/astro/test/fixtures/redirects/src/pages/secret.astro
diff --git a/packages/astro/test/fixtures/ssr-redirect/src/pages/test.astro b/packages/astro/test/fixtures/redirects/src/pages/test.astro
similarity index 100%
rename from packages/astro/test/fixtures/ssr-redirect/src/pages/test.astro
rename to packages/astro/test/fixtures/redirects/src/pages/test.astro
diff --git a/packages/astro/test/redirects.test.js b/packages/astro/test/redirects.test.js
index 999ab1f0f..a5a065309 100644
--- a/packages/astro/test/redirects.test.js
+++ b/packages/astro/test/redirects.test.js
@@ -9,7 +9,7 @@ describe('Astro.redirect', () => {
describe('output: "server"', () => {
before(async () => {
fixture = await loadFixture({
- root: './fixtures/ssr-redirect/',
+ root: './fixtures/redirects/',
output: 'server',
adapter: testAdapter(),
redirects: {
@@ -66,7 +66,7 @@ describe('Astro.redirect', () => {
before(async () => {
process.env.STATIC_MODE = true;
fixture = await loadFixture({
- root: './fixtures/ssr-redirect/',
+ root: './fixtures/redirects/',
output: 'static',
redirects: {
'/old': '/test',
@@ -78,6 +78,9 @@ describe('Astro.redirect', () => {
status: 302,
destination: '/test',
},
+ '/more/old/[dynamic]': '/more/[dynamic]',
+ '/more/old/[dynamic]/[route]': '/more/[dynamic]/[route]',
+ '/more/old/[...spread]': '/more/new/[...spread]',
},
});
await fixture.build();
@@ -149,6 +152,12 @@ describe('Astro.redirect', () => {
expect(html).to.include('http-equiv="refresh');
expect(html).to.include('url=/test');
});
+
+ it('falls back to spread rule when dynamic rules should not match', async () => {
+ const html = await fixture.readFile('/more/old/welcome/world/index.html');
+ expect(html).to.include('http-equiv="refresh');
+ expect(html).to.include('url=/more/new/welcome/world');
+ });
});
describe('dev', () => {
@@ -157,10 +166,13 @@ describe('Astro.redirect', () => {
before(async () => {
process.env.STATIC_MODE = true;
fixture = await loadFixture({
- root: './fixtures/ssr-redirect/',
+ root: './fixtures/redirects/',
output: 'static',
redirects: {
'/one': '/',
+ '/more/old/[dynamic]': '/more/[dynamic]',
+ '/more/old/[dynamic]/[route]': '/more/[dynamic]/[route]',
+ '/more/old/[...spread]': '/more/new/[...spread]',
},
});
devServer = await fixture.startDevServer();
@@ -170,11 +182,27 @@ describe('Astro.redirect', () => {
await devServer.stop();
});
- it('Returns 301', async () => {
+ it('performs simple redirects', async () => {
let res = await fixture.fetch('/one', {
redirect: 'manual',
});
expect(res.status).to.equal(301);
+ expect(res.headers.get('Location')).to.equal('/');
+ });
+
+ it('performs dynamic redirects', async () => {
+ const response = await fixture.fetch('/more/old/hello', { redirect: 'manual' });
+ expect(response.headers.get('Location')).to.equal('/more/hello');
+ });
+
+ it('performs dynamic redirects with multiple params', async () => {
+ const response = await fixture.fetch('/more/old/hello/world', { redirect: 'manual' });
+ expect(response.headers.get('Location')).to.equal('/more/hello/world');
+ });
+
+ it.skip('falls back to spread rule when dynamic rules should not match', async () => {
+ const response = await fixture.fetch('/more/old/welcome/world', { redirect: 'manual' });
+ expect(response.headers.get('Location')).to.equal('/more/new/welcome/world');
});
});
});
@@ -183,7 +211,7 @@ describe('Astro.redirect', () => {
before(async () => {
process.env.STATIC_MODE = true;
fixture = await loadFixture({
- root: './fixtures/ssr-redirect/',
+ root: './fixtures/redirects/',
output: 'static',
redirects: {
'/one': '/',
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 28fd2f162..addc09144 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -3054,6 +3054,12 @@ importers:
specifier: workspace:*
version: link:../../..
+ packages/astro/test/fixtures/redirects:
+ dependencies:
+ astro:
+ specifier: workspace:*
+ version: link:../../..
+
packages/astro/test/fixtures/reexport-astro-containing-client-component:
dependencies:
'@astrojs/preact':
@@ -3339,12 +3345,6 @@ importers:
specifier: workspace:*
version: link:../../..
- packages/astro/test/fixtures/ssr-redirect:
- dependencies:
- astro:
- specifier: workspace:*
- version: link:../../..
-
packages/astro/test/fixtures/ssr-request:
dependencies:
astro: