Hacktoberfest 2026: los issues que los mantenedores marcaron para octubre, abiertos y aptos para principiantes. Explorar issues de Hacktoberfest

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

Cerrado
#34,365 0 comentarios 0 reacciones 0 asignados Ver en GitHub

Los mantenedores suelen responder en 1 día

Nadie ha tomado este issue todavía.

  • #34366 de @SkyZeroZx — cerrado sin fusionar

Evaluación

Dificultad
3/5
Tiempo estimado
Medio día
Aptitud para principiantes
30/100
Tipo de issue
Error
Claridad
Bastante claro
Estado de actividad
Activo
Stack tecnológico
angular, nginx, nodejs, typescript
Área
backend

Línea de trabajo

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.

Escrito por el modelo de indexación a partir del texto del issue.

Descripción

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
Lenguaje dominante
TypeScript
Estrellas
27k
Forks
11.8k
Merge medio
1 d 6 h
PR fusionados (30 d)
216

Preparar el entorno

Primeros pasos

  1. Lee el issue completo y luego la guía de contribución del proyecto.
  2. Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
  3. Haz un fork del repositorio y trabaja en una rama.
  4. Abre un pull request que haga referencia al número del issue.

Más de angular/angular-cli

Todos los issues de angular/angular-cli

Issues similares

Más issues de TypeScript

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.