Skip to content

fix(redirects): respect quoted CSV fields and read the type case-insensitively - #521

Draft
igoramf wants to merge 1 commit into
mainfrom
fix/redirect-csv-parsing
Draft

fix(redirects): respect quoted CSV fields and read the type case-insensitively#521
igoramf wants to merge 1 commit into
mainfrom
fix/redirect-csv-parsing

Conversation

@igoramf

@igoramf igoramf commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

Dois bugs de parsing achados investigando um loop de redirect. Nenhum dos dois causa o loop (isso é o #519) e nenhum depende do outro — mas os dois corrompem dado real, e são pequenos o bastante para irem juntos.

Independente do #519 e do #520; pode mergear em qualquer ordem. Encosta em parseRedirectsCsv, então espere um conflito trivial com o #519.

1. split(",") ignorava aspas

Exports de redirect em massa citam linhas cuja query contém vírgula — o padrão de URL de categoria do VTEX:

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

O split cru quebrava nas vírgulas de dentro das aspas, produzindo:

from: /"https://www.montecarlo.com.br/relogios?map=category-1
to:   category-2"

Num CSV de produção, 643 das 3017 linhas saíram assim, com um pedaço da query como destino: to: "c", to: "priceFrom", to: "specificationFilter_29". Hoje elas são inofensivas só por acidente — a origem mutilada (/"https://…) nunca casa com request nenhuma. Mas é 1/5 do arquivo virando lixo silencioso, e a próxima linha citada que não comece com http vira uma regra ativa apontando para um destino inventado.

Agora o split respeita aspas, incluindo "" escapado (RFC 4180).

2. PERMANENT virava 302

status: type === "permanent" || type === "301" ? 301 : 302

Exports escrevem PERMANENT em caixa alta. Como só a grafia minúscula casava, todos os ~3000 redirects daquele site serviam 302. Redirect temporário não passa sinal de ranking para a URL nova — a migração inteira jogou fora o valor de SEO das URLs antigas, sem erro nenhum em log.

Agora o tipo é lido sem diferenciar caixa, no CSV e nos blocos de CMS.

Testes

packages/blocks/src/sdk/redirectsCsvParsing.test.ts, 8 casos. 5 falham no main:

git stash -- packages/blocks/src/sdk/redirects.ts
vitest run packages/blocks/src/sdk/redirectsCsvParsing.test.ts
→ Tests  5 failed | 3 passed (8)

Um dos casos documenta a fronteira em vez de esconder: uma linha sem aspas cuja query tem vírgula continua sendo picada. Aspas são o que torna a vírgula literal; adivinhar seria pior que falhar.

Suíte do pacote: 746 passed (56 arquivos).

Contexto

🤖 Generated with Claude Code


Summary by cubic

Fixes two independent bugs in parseRedirectsCsv — quoted CSV fields were split on commas inside quotes, and uppercase PERMANENT redirect types were served as 302.

  • Quoted fields no longer split on commas, and "" is unescaped per RFC 4180; previously, 643 of 3017 rows in one production export had a query fragment as their target.
  • Redirect status is now read case-insensitively: PERMANENT, Permanent, permanent, and 301 all map to 301, in both CSV and CMS block redirects.
  • Unquoted rows whose query contains a comma still split; only quoting makes a comma literal, and a test documents that boundary.

Written for commit 59f5477. Summary will update on new commits.

Review in cubic

…nsitively

Two independent parsing bugs found while investigating a redirect loop; neither
causes the loop, both corrupt real data.

Quoted fields: `parseRedirectsCsv` split on every comma, but bulk exports quote
rows whose query contains one:

    "https://site/relogios?map=category-1,category-2",/relogios,PERMANENT

That row parsed as from=`/"https://site/relogios?map=category-1`,
to=`category-2"`. In one production CSV, 643 of 3017 rows came out with a
fragment of a query as their target (`to: "c"`, `to: "priceFrom"`). They are
inert today only because the mangled source never matches a request.

Type spelling: only lowercase `permanent` mapped to 301. Exports commonly write
`PERMANENT`, so every one of that site's ~3000 redirects served 302 — a
temporary redirect passes no ranking signal to the new URL, silently discarding
the SEO value of the migration.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
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