Skip to content

Fix redirect targets when a param value contains a $ replacement pattern - #18002

Merged
ematipico merged 2 commits into
withastro:mainfrom
shoutoutuoadi325:fix/redirect-param-replacement-patterns
Sep 16, 2026
Merged

ematipico merged 2 commits into
withastro:mainfrom
shoutoutuoadi325:fix/redirect-param-replacement-patterns

Conversation

@shoutoutuoadi325

@shoutoutuoadi325 shoutoutuoadi325 commented Sep 15, 2026 •

Copy link
Copy Markdown
Contributor

Changes

Closes #18010

  • Substitutes dynamic params in string redirect targets using a replacer function, so the value is inserted literally. String.replace was expanding $-prefixed replacement sequences found in the param value: with redirects: { '/old/[slug]': '/new/[slug]' }, a request to /old/a$&b produced Location: /new/a[slug]b, and a slug of x$`y produced /new/x/new/y.

Testing

  • Adds resolveRedirectTarget cases for $&, $` and $' occurring inside a param value.

Docs

  • No docs update needed, this restores the documented behavior of redirects with dynamic params.

Copilot AI lite review requested due to automatic review settings September 15, 2026 09:02
@changeset-bot

changeset-bot Bot commented Sep 15, 2026 •

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: dd41e31

The changes in this PR will be included in the next version bump.

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@github-actions github-actions Bot added the pkg: astro Related to the core `astro` package (scope) label Sep 15, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Follow-up documentation and spread-parameter regression coverage are requested.

Get a fresh assessment by requesting another Copilot review.

Pull request overview

Fixes dynamic redirect targets so $ sequences in parameter values are inserted literally.

Changes:

  • Uses replacer callbacks for literal parameter substitution.
  • Adds regression coverage for $ replacement patterns.
  • Adds an Astro patch changeset.
File summaries
File Description
packages/astro/test/units/redirects/render.test.ts Adds regression tests for dynamic redirect parameters.
packages/astro/src/core/redirects/render.ts Fixes literal parameter substitution.
.changeset/tired-rats-design.md Records the patch release.
Review details

Suppressed comments (1)

packages/astro/src/core/redirects/render.ts:64

  • The same regression is reachable through the spread placeholder on this line: a value such as rest: 'x$&y' with /new/[...rest] would expand $& if this callback regresses to a replacement string, while the existing spread test only uses a/b/c. Add a regression assertion for a spread value containing a replacement pattern so both substitution forms are protected.
					.replace(`[...${param}]`, () => paramValue);
  • Files reviewed: 3/3 changed files
  • Comments generated: 1
  • Review effort level: Lite

💡 Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

for (const param of Object.keys(params)) {
const paramValue = params[param]!;
target = target.replace(`[${param}]`, paramValue).replace(`[...${param}]`, paramValue);
// Pass a replacer so `$`-prefixed sequences in the param value are inserted literally
@codspeed

codspeed Bot commented Sep 15, 2026 •

Copy link
Copy Markdown

Merging this PR will not alter performance

✅ 21 untouched benchmarks


Comparing shoutoutuoadi325:fix/redirect-param-replacement-patterns (dd41e31) with main (590df61)1

Open in CodSpeed

Footnotes

  1. No successful run was found on main (4464b3a) during the generation of this report, so 590df61 was used instead as the comparison base. There might be some changes unrelated to this pull request in this report. ↩

@ematipico ematipico left a comment •

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please file a bug report first

@ematipico ematipico closed this Sep 15, 2026
@shoutoutuoadi325

Copy link
Copy Markdown
Contributor Author

Bug report filed as #18010, with a minimal reproduction at https://github.com/shoutoutuoadi325/astro-redirect-dollar-repro. Also pushed a commit adding a [...rest] case to the unit tests and an issue link to the code comment. Could this be reopened?

@ematipico ematipico reopened this Sep 16, 2026
@ematipico
ematipico merged commit 312ab49 into withastro:main Sep 16, 2026
38 of 47 checks passed
@astrobot-houston astrobot-houston mentioned this pull request Sep 16, 2026
dadezzz pushed a commit to dadezzz/university_notes that referenced this pull request Sep 20, 2026
This PR contains the following updates:

| Package | Change | [Age](https://docs.renovatebot.com/merge-confidence/) | [Confidence](https://docs.renovatebot.com/merge-confidence/) |
|---|---|---|---|
| [astro](https://astro.build) ([source](https://github.com/withastro/astro/tree/HEAD/packages/astro)) | [`7.3.2` → `7.3.3`](https://renovatebot.com/diffs/npm/astro/7.3.2/7.3.3) | ![age](https://developer.mend.io/api/mc/badges/age/npm/astro/7.3.3?slim=true) | ![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/astro/7.3.2/7.3.3?slim=true) |

---

### Release Notes

<details>
<summary>withastro/astro (astro)</summary>

### [`v7.3.3`](https://github.com/withastro/astro/blob/HEAD/packages/astro/CHANGELOG.md#733)

[Compare Source](https://github.com/withastro/astro/compare/astro@7.3.2...astro@7.3.3)

##### Patch Changes

- [#&#8203;17651](withastro/astro#17651) [`504333c`](withastro/astro@504333c) Thanks [@&#8203;sxzz](https://github.com/sxzz)! - Refactors internal version handling to use a smaller, ESM-native dependency

- [#&#8203;17942](withastro/astro#17942) [`0bc5715`](withastro/astro@0bc5715) Thanks [@&#8203;matthewp](https://github.com/matthewp)! - Returns appropriate 400 and 404 responses from the image endpoint for invalid and missing local image paths

- [#&#8203;17700](withastro/astro#17700) [`b2222fc`](withastro/astro@b2222fc) Thanks [@&#8203;winklemad](https://github.com/winklemad)! - Fixes `Astro.preferredLocaleList` returning an empty list when a locale is configured with the object form (`{ path, codes }`) and the browser sends the code with different casing or an underscore, such as `en-US` matching a configured `en-us`

- [#&#8203;17941](withastro/astro#17941) [`394ff79`](withastro/astro@394ff79) Thanks [@&#8203;matthewp](https://github.com/matthewp)! - Fixes `astro preview --ignore-lock` (and `astro dev --ignore-lock`) being refused when run from an AI agent environment. The flag now starts the server in the foreground instead of erroring, since agent detection only inferred background mode and was never explicitly requested. An explicit `--background` combined with `--ignore-lock` still errors.

- [#&#8203;17928](withastro/astro#17928) [`3277927`](withastro/astro@3277927) Thanks [@&#8203;ArmandPhilippot](https://github.com/ArmandPhilippot)! - Fixes TypeScript autocompletion for `getImage()` to suggest all available predefined options.

- [#&#8203;17928](withastro/astro#17928) [`3277927`](withastro/astro@3277927) Thanks [@&#8203;ArmandPhilippot](https://github.com/ArmandPhilippot)! - Fixes a type error in `getImage()` options that allowed passing both `widths` and `densities` at the same time.

- [#&#8203;17857](withastro/astro#17857) [`2637ed1`](withastro/astro@2637ed1) Thanks [@&#8203;Princesseuh](https://github.com/Princesseuh)! - Improves rendering performance

- [#&#8203;17943](withastro/astro#17943) [`2fc7ce9`](withastro/astro@2fc7ce9) Thanks [@&#8203;matthewp](https://github.com/matthewp)! - Fixes a WebAssembly error when importing `astro:actions` in tests that run under `@cloudflare/vitest-pool-workers`

- [#&#8203;18018](withastro/astro#18018) [`1b5a234`](withastro/astro@1b5a234) Thanks [@&#8203;astro-factory](https://github.com/apps/astro-factory)! - Fixes trailing-slash redirect response body pointing to the incoming URL instead of the redirect target. The `location` header was correct, but the HTML body (`<meta http-equiv="refresh">`, `<title>`, and `<a>` tag) contained the original request path without the trailing-slash correction or query string.

- [#&#8203;17905](withastro/astro#17905) [`eaf70fa`](withastro/astro@eaf70fa) Thanks [@&#8203;SudoDevStudio](https://github.com/SudoDevStudio)! - Fixes custom dev toolbar apps losing their UI after client-side navigation with `<ClientRouter />`.

- [#&#8203;18011](withastro/astro#18011) [`558b301`](withastro/astro@558b301) Thanks [@&#8203;astro-factory](https://github.com/apps/astro-factory)! - Fixes prerendered Cloudflare pages rendering as `[object Object]` when `nodejs_compat` is enabled in `wrangler.toml`

- [#&#8203;17944](withastro/astro#17944) [`ba08e35`](withastro/astro@ba08e35) Thanks [@&#8203;matthewp](https://github.com/matthewp)! - Fixes a regression in `astro dev` where writes outside the module graph (for example, `@astrojs/cloudflare`'s `.wrangler/state` files) invalidated the middleware on every request, causing repeated SSR reloads. Such writes no longer invalidate the middleware.

- [#&#8203;17531](withastro/astro#17531) [`ae837db`](withastro/astro@ae837db) Thanks [@&#8203;danilloestrela](https://github.com/danilloestrela)! - Updates `svgo` to `4.0.2` to resolve a security advisory

- [#&#8203;17953](withastro/astro#17953) [`dbbf10e`](withastro/astro@dbbf10e) Thanks [@&#8203;astro-factory](https://github.com/apps/astro-factory)! - Fixes a one-time page reload shortly after the first load on cold dev-server starts when a project has framework components imported from MDX content entries. MDX files are now included in the dev dependency pre-bundling scan, so their framework dependencies are bundled up front instead of being discovered (and reloaded for) at runtime.

- [#&#8203;17955](withastro/astro#17955) [`4e8ad9a`](withastro/astro@4e8ad9a) Thanks [@&#8203;matthewp](https://github.com/matthewp)! - Improves dev server startup time. The content config and dev server app module graphs now begin compiling during server creation without blocking the server from listening. Request handling waits for the shared setup result when needed, cutting `astro dev` ready time by roughly a third on projects with a content config.

- [#&#8203;17960](withastro/astro#17960) [`9838049`](withastro/astro@9838049) Thanks [@&#8203;Chy-Zaber-Bin-Zahid](https://github.com/Chy-Zaber-Bin-Zahid)! - Improves the diagnostics of some Astro errors.

- [#&#8203;17998](withastro/astro#17998) [`0e5478d`](withastro/astro@0e5478d) Thanks [@&#8203;astro-factory](https://github.com/apps/astro-factory)! - Fixes SVG `<style>` elements nested inside `<defs>` or other container elements not being hashed for CSP

- [#&#8203;17994](withastro/astro#17994) [`80f9f1d`](withastro/astro@80f9f1d) Thanks [@&#8203;astro-factory](https://github.com/apps/astro-factory)! - Fixes `experimental.incrementalBuild` restoring pages with stale CSS after a preprocessor partial changes or missing original images referenced by restored pages

- [#&#8203;17889](withastro/astro#17889) [`8ae6b46`](withastro/astro@8ae6b46) Thanks [@&#8203;ajfAfg](https://github.com/ajfAfg)! - Fixes a bug where the dev server stripped the configured `base` from URLs that only share a prefix with it. With `base: '/s'`, requests to `/src/...` were rewritten to `/rc/...` and failed, breaking those pages during development.

- [#&#8203;17980](withastro/astro#17980) [`cfccafa`](withastro/astro@cfccafa) Thanks [@&#8203;gameroman](https://github.com/gameroman)! - Improves JSDoc for fonts api

- [#&#8203;17953](withastro/astro#17953) [`dbbf10e`](withastro/astro@dbbf10e) Thanks [@&#8203;astro-factory](https://github.com/apps/astro-factory)! - Fixes CSS HMR for framework components rendered through content entries after `ClientRouter` navigation

- [#&#8203;17970](withastro/astro#17970) [`0b4dc3a`](withastro/astro@0b4dc3a) Thanks [@&#8203;matthewp](https://github.com/matthewp)! - Improves serialization of transition animation values in generated CSS

- [#&#8203;17999](withastro/astro#17999) [`30ef3cb`](withastro/astro@30ef3cb) Thanks [@&#8203;astro-factory](https://github.com/apps/astro-factory)! - Fixes content collection HMR not updating prerendered pages when an adapter enables a separate prerender environment (e.g. `@astrojs/cloudflare` with `prerenderEnvironment: 'node'`)

- [#&#8203;18002](withastro/astro#18002) [`312ab49`](withastro/astro@312ab49) Thanks [@&#8203;shoutoutuoadi325](https://github.com/shoutoutuoadi325)! - Fixes redirect targets being corrupted when a dynamic route parameter value contains `$` replacement patterns like `$&`

- [#&#8203;17937](withastro/astro#17937) [`e294953`](withastro/astro@e294953) Thanks [@&#8203;matthewp](https://github.com/matthewp)! - Fixes a bug where the `glob()` content loader kept stale entries in the data store after the last file in a collection was deleted. Empty collections are now pruned correctly, and the file watcher is registered in dev so the first file added to an empty collection is picked up without a restart.

- [#&#8203;17945](withastro/astro#17945) [`750b4db`](withastro/astro@750b4db) Thanks [@&#8203;matthewp](https://github.com/matthewp)! - Pre-bundles renderer server entrypoints and the default console logger during dev so they are included in the initial optimization pass, preventing a mid-request re-optimization that could crash the dev server on Cloudflare (workerd).

</details>

---

### Configuration

📅 **Schedule**: (UTC)

- Branch creation
  - At any time (no schedule defined)
- Automerge
  - At any time (no schedule defined)

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box

---

This PR has been generated by [Mend Renovate CLI](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0NC4xMDMuMiIsInVwZGF0ZWRJblZlciI6IjQ0LjEwMy4yIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

pkg: astro Related to the core `astro` package (scope)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Redirect Location is corrupted when a route param value contains $ replacement patterns

3 participants