Hacktoberfest 2026:维护者为十月标记出来的 issue,仍然开放、适合新手。 浏览 Hacktoberfest issue

Angular SSR redirects can take healthy proxies upstreams out of rotation through an unbounded Location header

未关闭
#34,365 0 条评论 0 个 reaction 已指派 0 人 在 GitHub 查看

维护者通常 1 天内回复

@SkyZeroZx 已经在做这个了。

开始于 2026年10月15日。

  • #34366 来自 @SkyZeroZx —— 未关闭

评估

难度
3/5
预计耗时
半天
新手友好度
30/100
Issue 类型
缺陷
描述清晰度
基本清楚
活跃度
活跃
技术栈
angular, nginx, nodejs, typescript
领域
backend

调研方向

Start with createRedirectResponse() in the Angular SSR package, where resHeaders.set("Location", location) sets the header without a length check, and with the render-redirect path from #31497 that sends the Router's final URL. Linked PR #34366 is already open against this issue, so read it first. Reproduce with the lab repo linked in the issue, using a long query string. Done means the response no longer produces an oversized Location for such requests, with a test covering it.

由索引模型根据 Issue 内容生成。

描述

area: @angular/ssr
Description

createRedirectResponse() sets Location from request data without any length limit:

resHeaders.set("Location", location);

Route redirects copy request path segments into a relative redirectTo, and render redirects send the Router's final URL, query included, when it differs from the request (#31497). Both are intended, but nothing bounds the size. The header is at least as large as the request, and percent-encoding on the way makes it bigger: new URL() encodes " ' < > and the Router's query serializer encodes characters like / = ? |, so it is about 3x a raw request, and about 5x when a guard puts state.url in returnUrl and the % is encoded again. Both encodings are correct.

Behind nginx this affects other users. The response doesn't fit in nginx's default 4k proxy_buffer_size, so nginx answers 502 and counts it as a failed attempt for that backend (max_fails=1, fail_timeout=10s). With two backends and one worker, two unauthenticated GETs leave the upstream empty and every request gets 502 for about ten seconds, while both Node processes are fine.

I think this is bit similar as unpoly-rails GHSA-m875-3xf6-mf78.

A buffer sized for the app's largest redirect avoids it, but nothing tells the operator that size and it changes when someone adds a guard: for the plain returnUrl guard at nginx's 8 KB request line it is about 40 KB. max_fails=0 also avoids it, by turning passive health checks off.

The app doesn't need any redirect. With the server routes on RenderMode.Server, as in the SSR guide, this request gets a 302 with a 4,208 B Location:

GET /home/(x)?q=<1,400 raw ">     1,412 B

The ** route drops the unmatched (x) group, so the Router ends on /home?q=.... In the browser that is a replaceState; on the server #31497 turns it into a 302. Nothing in the Router needs to change.

Minimal Reproduction
// app.routes.ts
export const routes: Routes = [
  { path: "", component: Home },
  { path: "home", component: Home },
  { path: "**", component: NotFound },
];

// app.routes.server.ts
export const serverRoutes: ServerRoute[] = [
  { path: "**", renderMode: RenderMode.Server },
];
ng build
NG_ALLOWED_HOSTS=localhost PORT=4000 node dist/app/server/server.mjs &
NG_ALLOWED_HOSTS=localhost PORT=4001 node dist/app/server/server.mjs &

nginx with one worker and nothing else tuned:

worker_processes 1;
events {}
http {
  upstream ssr {
    server 127.0.0.1:4000;
    server 127.0.0.1:4001;
  }
  server {
    listen 8080;
    location / {
      proxy_pass http://ssr;
      proxy_set_header Host localhost;
    }
  }
}

The request has to go out raw, fetch and node:http percent-encode the quotes first. I sent one per second for 25 s while normal traffic hit /home, and counted until /home answered 200 again:

Setup /home OK
nginx, the config above 15.2%
nginx, Compose service with two replicas 9.5%
nginx image as shipped on 2 vCPUs (two workers) 25.2%
nginx, worker_processes auto with a shared zone 9.3%
OpenResty, plain upstream 4.8%
Kong 3.7, passive checks with 502 in unhealthy.http_statuses 1.3%
nginx, one backend 100%
Same setups without those requests 100%

I also reproduced it on a VPS with nginx behind Cloudflare.

See https://github.com/SkyZeroZx/angular-ssr-location-lab

Exception or Error
[error] upstream sent too big header while reading response header from upstream, request: "GET /home/(x)?q=..."
[warn] upstream server temporarily disabled while reading response header from upstream
[error] no live upstreams while connecting to upstream, request: "GET /home HTTP/1.1"
Your Environment
Angular CLI       22.2.2
@angular/ssr      22.2.2
@angular/core     22.2.2
@angular/router   22.2.2
Node.js           22.23.3
Build             production
Engine            AngularNodeAppEngine
Render mode       RenderMode.Server
nginx             1.27.5, 1.29.3, 1.30.4 and 1.31.2
主要语言
TypeScript
星标
27k
派生
11.8k
平均合并
1 天 3 小时
30 天内合并 PR
193

环境准备

从这里开始

  1. 先读完整个 Issue,再读项目的贡献指南。
  2. 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
  3. Fork 仓库,在一个分支上完成修改。
  4. 提交 Pull Request,并在描述里引用这个 Issue 编号。

angular/angular-cli 的其他 Issue

查看 angular/angular-cli 的全部 Issue

相似的 Issue

更多 TypeScript Issue

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。