SSR resolves relative `redirectTo` against the wrong base when the route path has several segments
Maintainer thường phản hồi trong vòng 1 ngày
Một pull request liên quan đã được merge.
- #34301 của @bschaeublin — đã merge
Đánh giá
- Độ khó
- 3/5
- Thời gian dự kiến
- 1-2 ngày
- Mức phù hợp với người mới
- 45/100
Hướng nghiên cứu
The bug sits in resolveRedirectTo in packages/angular/ssr/src/routes/ng-routes.ts, which pops only the last segment where the router replaces all segments the route consumes. Start by reading that function, then the redirect/relative case in packages/angular/ssr/test/app_spec.ts. Done means a multi-segment relative redirectTo resolves to the router's result, with the two existing app_spec expectations updated. The issue author already has a fix and PR planned, and it changes current behaviour, so coordinate with them first.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Mô tả
Command
other
Is this a regression?
- Yes, this behavior used to work in the previous version
The previous version in which this bug was not present was
No response
Description
When a request matches a route with a string redirectTo, @angular/ssr answers with a 302 built from the route config, without running the router. If the route's own path has more than one segment, a relative redirectTo is resolved against the wrong base.
{ path: 'old/page', redirectTo: 'new/page' }:
- Server:
GET /old/pagereturnsLocation: /old/new/page(a 404). - Router (in-app navigation to
/old/page):/new/page.
The router replaces all segments matched by the redirecting route (old/page). The server only removes the last one (page). Routes whose path is a single segment or empty are not affected, which is probably why this has gone unnoticed.
Note: fixing this changes current behaviour. app_spec.ts asserts the current result (L207-L217: redirect/relative → /redirect/home, the router gives /home), and an app could depend on it if it happens to have a route at the server-computed path.
Minimal Reproduction
npx @angular/[email protected] new repro-app --ssr --defaults
cd repro-app
src/app/app.routes.ts:
import { Component } from '@angular/core';
import { Routes } from '@angular/router';
@Component({ template: 'New page' })
class NewPage {}
export const routes: Routes = [
{ path: 'old/page', redirectTo: 'new/page' },
{ path: 'new/page', component: NewPage },
];
src/app/app.routes.server.ts (server rendering, so the request reaches the redirect handling instead of a prerendered redirect page):
import { RenderMode, ServerRoute } from '@angular/ssr';
export const serverRoutes: ServerRoute[] = [{ path: '**', renderMode: RenderMode.Server }];
npx ng build
NG_ALLOWED_HOSTS=localhost PORT=4000 node dist/repro-app/server/server.mjs
curl -si 'localhost:4000/old/page' | grep -i '^location'
Expected: location: /new/page (where the router navigates). Actual: location: /old/new/page.
Exception or Error
$ curl -si localhost:4000/old/page | head -3
HTTP/1.1 302 Found
X-Powered-By: Express
location: /old/new/page
Your Environment
_ _ ____ _ ___
/ \ _ __ __ _ _ _| | __ _ _ __ / ___| | |_ _|
/ △ \ | '_ \ / _` | | | | |/ _` | '__| | | | | | |
/ ___ \| | | | (_| | |_| | | (_| | | | |___| |___ | |
/_/ \_\_| |_|\__, |\__,_|_|\__,_|_| \____|_____|___|
|___/
Angular CLI : 22.2.2
Angular : 22.2.2
Node.js : 24.18.0
Package Manager : npm 11.16.0
Operating System : linux x64
┌───────────────────────────┬───────────────────┬───────────────────┐
│ Package │ Installed Version │ Requested Version │
├───────────────────────────┼───────────────────┼───────────────────┤
│ @angular/build │ 22.2.2 │ ^22.2.2 │
│ @angular/cli │ 22.2.2 │ ^22.2.2 │
│ @angular/common │ 22.2.2 │ ^22.2.0 │
│ @angular/compiler │ 22.2.2 │ ^22.2.0 │
│ @angular/compiler-cli │ 22.2.2 │ ^22.2.0 │
│ @angular/core │ 22.2.2 │ ^22.2.0 │
│ @angular/forms │ 22.2.2 │ ^22.2.0 │
│ @angular/platform-browser │ 22.2.2 │ ^22.2.0 │
│ @angular/platform-server │ 22.2.2 │ ^22.2.0 │
│ @angular/router │ 22.2.2 │ ^22.2.0 │
│ @angular/ssr │ 22.2.2 │ ^22.2.2 │
│ rxjs │ 7.8.2 │ ~7.8.0 │
│ typescript │ 6.0.3 │ ~6.0.2 │
└───────────────────────────┴───────────────────┴───────────────────┘
Anything else relevant?
resolveRedirectTo in ng-routes.ts#L543-L554 removes one segment (segments.pop()), while the router's applyRedirectCommands replaces all segments consumed by the route.
Related: #33504 / #33516 (parameters in the same function).
I have a fix with tests and will open a PR for it. It updates the two app_spec expectations above to the router's result. If the current behaviour is intended, or this should wait for a major, I'm happy to adjust.
Not browser specific. Seen with the default Express server.ts generated by ng new --ssr; the redirect comes from AngularNodeAppEngine.handle(), not from Express itself.
- Ngôn ngữ chính
- TypeScript
- Star
- 27k
- Fork
- 11.8k
- Merge trung bình
- 1 ngày 4 giờ
- Pull request đã merge (30 ngày)
- 168
Chuẩn bị môi trường
- Không có Dockerfile hay tệp Docker Compose
- Có mẫu pull request
- Đọc hướng dẫn đóng góp
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Issue khác của angular/angular-cli
-
area: @angular/cli
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 78/100
angular/angular-cli#34307 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Can't use an array of hostnames in --allowedHosts cli parameter in @angular/build:dev-serverĐang mởarea: @angular/build gemini-triaged
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 74/100
angular/angular-cli#33955 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
area: @angular/cli gemini-triaged
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 72/100
angular/angular-cli#33055 · 1 bình luận · 3 reaction ·
Maintainer thường phản hồi trong vòng 1 ngày
-
area: @angular/build
Độ khó 4/5 3-5 ngày Mức phù hợp với người mới 22/100
angular/angular-cli#34335 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
@angular/ssr: page under nested empty-path routes is prerendered without the modulepreload hints of its lazy chunks (regression since 19.1.6)Có thể đã có người làm @alan-agius4 đã nhận 2 ngày trước. Đang mởarea: @angular/ssr
angular/angular-cli#34320 · 1 người được giao ·
Maintainer thường phản hồi trong vòng 1 ngày
Tất cả issue của angular/angular-cli
Issue tương tự
-
useFragment does not require `variables` when the fragment's variables type has required fieldsĐang mở
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 75/100
apollographql/apollo-client#13493 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Custom hosts written as trailing-dot FQDNs (`host.local.`) aren't detected as local backendsCó thể đã có người làm @roboomp đã nhận hôm nay. Đang mởbug prio:p2 providers triaged
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 82/100
can1357/oh-my-pi#15798 · 3 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 62/100
code-yeongyu/oh-my-openagent#10172 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 70/100
PDFCraftTool/pdfcraft#189 ·
-
Add the Yahoo chart API duplicate last-day row (yfinance#573) to incidents.md (about 1 hour)Có thể đã có người làm Có pull request liên kết đang mở hoặc đã được merge. Đang mởdata docs good first issue
Độ khó 1/5 Dưới một giờ Mức phù hợp với người mới 80/100
pacocartones/market-data-sanity-checker#160 ·
Maintainer thường phản hồi trong vòng 1 ngày