Skip to content

fix(redirects): drop self-redirects at load time instead of serving a loop - #519

Draft
igoramf wants to merge 1 commit into
mainfrom
fix/redirect-csv-query-self-loop
Draft

fix(redirects): drop self-redirects at load time instead of serving a loop#519
igoramf wants to merge 1 commit into
mainfrom
fix/redirect-csv-query-self-loop

Conversation

@igoramf

@igoramf igoramf commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

Primeiro de três PRs saídos do mesmo incidente. Este é o fix do bug; os outros dois estão listados no fim.

O bug

Uma regra cuja origem e destino resolvem para a mesma página responde toda request com um redirect para a URL que o browser acabou de pedir → ERR_TOO_MANY_REDIRECTS.

Exports de migração em massa trazem essas linhas prontas, e o normalizePath fabrica mais: ele reduz um from absoluto a new URL(p).pathname, e pathname não inclui a query. Então uma linha que só queria limpar uma URL legada de categoria:

https://www.montecarlo.com.br/aliancas?map=category-1,/aliancas,PERMANENT

vira exact["/aliancas"] = { to: "/aliancas" } e derruba a página inteira.

Aconteceu duas vezes no mesmo storefront, a partir do mesmo CSV:

Linha Página derrubada
http://blog.montecarlo.com.br/,/,PERMANENT home
https://www.montecarlo.com.br/aliancas?map=category-1,/aliancas,PERMANENT /aliancas

Nas duas vezes o contorno foi apagar a linha do CSV. Isso não escala: são ~3000 linhas de dump, e qualquer sync futuro reintroduz.

Por que o loader Fresh não tinha isso

deco-cx/apps@0.161.0/website/loaders/redirectsFromCsv.ts, que este SDK substituiu:

if (!from || !to || from === to) continue;

O guard existia. O port perdeu. Este PR devolve, comparando depois da normalização — é justamente aí que as linhas acima colapsam.

Comportamento

Regra Antes Depois
/a → /a loop descartada no load
https://site/x?q=1 → /x loop descartada no load
http://blog.site/ → / loop descartada no load
/a/ → /a, /A → /a loop descartada no load
/x → /x?ref=1 loop (o destino recasa) descartada no load
/x → https://other.site/x ok ok — host difere
/old → /new, /blog/* → /news/* ok ok

O host é comparado sempre que os dois lados carregam um, então redirect cross-origin para o mesmo path continua disparando.

Testes

packages/blocks/src/sdk/redirects.test.ts, 9 casos montados sobre as linhas reais do CSV do incidente. 7 falham no main:

git stash -- packages/blocks/src/sdk/redirects.ts
vitest run packages/blocks/src/sdk/redirects.test.ts
→ Tests  7 failed | 2 passed (9)

Com o patch: 9/9. Suíte do pacote: 756 passed (56 arquivos).

Trade-off que este PR assume

O guard descarta a regra em vez de consertá-la. ?map=category-1 → /aliancas é um redirect legítimo, que o Fresh honra hoje casando a href inteira (isHref: true), e aqui ele morre silenciosamente. É a escolha certa para um fix de loop — melhor perder um redirect do que derrubar uma página — mas é perda de comportamento.

Restaurar isso é o assunto do PR seguinte, empilhado neste:

🤖 Generated with Claude Code

@igoramf
igoramf force-pushed the fix/redirect-csv-query-self-loop branch from 06855ee to 6f611cc Compare September 1, 2026 10:55
@igoramf igoramf changed the title fix(redirects): query-scoped CSV rows no longer hijack (and loop on) the bare path fix(redirects): drop self-redirects at load time instead of serving a loop Sep 1, 2026
… loop

A rule whose source and target resolve to the same page answers every request
with a redirect back to the URL just asked for: ERR_TOO_MANY_REDIRECTS.

Bulk migration exports carry these rows, and `normalizePath` manufactures more:
it reduces an absolute `from` to `new URL(p).pathname`, which drops the query.
A row scoped to one legacy query

    https://www.example.com/aliancas?map=category-1  ->  /aliancas

therefore becomes `/aliancas -> /aliancas` and takes the page down. One
production storefront hit this twice from the same CSV — once on `/`, via a
`http://blog.example.com/,/` row, and once on a category page.

The Fresh loader this SDK replaced (deco-cx/apps
`website/loaders/redirectsFromCsv.ts`) had a `from === to` guard for exactly
this. Restore it, comparing after normalization so the collapsed rows above are
caught too.

Host is compared whenever both sides carry one, so a genuine cross-origin
redirect to the same path (`/x -> https://other.example.com/x`) still fires.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@igoramf
igoramf force-pushed the fix/redirect-csv-query-self-loop branch from 6f611cc to e5b07c7 Compare September 1, 2026 11:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant