Skip to content

Commit 312ab49

Browse files
Fix redirect targets when a param value contains a $ replacement pattern (#18002)
1 parent 1b5a234 commit 312ab49

3 files changed

Lines changed: 28 additions & 1 deletion

File tree

‎.changeset/tired-rats-design.md‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'astro': patch
3+
---
4+
5+
Fixes redirect targets being corrupted when a dynamic route parameter value contains `$` replacement patterns like `$&`

‎packages/astro/src/core/redirects/render.ts‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,10 @@ export function resolveRedirectTarget(
5858
let target = redirect;
5959
for (const param of Object.keys(params)) {
6060
const paramValue = params[param]!;
61-
target = target.replace(`[${param}]`, paramValue).replace(`[...${param}]`, paramValue);
61+
// Pass a replacer so `$`-prefixed sequences in the param value are inserted literally (#18010)
62+
target = target
63+
.replace(`[${param}]`, () => paramValue)
64+
.replace(`[...${param}]`, () => paramValue);
6265
}
6366
return target;
6467
}

‎packages/astro/test/units/redirects/render.test.ts‎

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,25 @@ describe('resolveRedirectTarget', () => {
241241
);
242242
});
243243

244+
it('substitutes a param value containing replacement patterns literally', () => {
245+
assert.equal(
246+
resolveRedirectTarget({ slug: 'a$&b' }, '/new/[slug]', undefined, 'ignore'),
247+
'/new/a$&b',
248+
);
249+
assert.equal(
250+
resolveRedirectTarget({ slug: 'x$`y' }, '/new/[slug]', undefined, 'ignore'),
251+
'/new/x$`y',
252+
);
253+
assert.equal(
254+
resolveRedirectTarget({ slug: "a$'b" }, '/new/[slug]', undefined, 'ignore'),
255+
"/new/a$'b",
256+
);
257+
assert.equal(
258+
resolveRedirectTarget({ rest: 'x$&y/z' }, '/new/[...rest]', undefined, 'ignore'),
259+
'/new/x$&y/z',
260+
);
261+
});
262+
244263
it('returns the string as-is when there are no params', () => {
245264
assert.equal(resolveRedirectTarget({}, '/destination', undefined, 'ignore'), '/destination');
246265
});

0 commit comments

Comments
 (0)