fix(routes): constrain year and month params to numbers - #3
Open
Guajir0-code wants to merge 1 commit into
Open
Conversation
/{year}/{month} and /{year}/{month}/{slug} carried no constraints, so they
matched any 2- and 3-segment path. /foo/bar rendered an empty YearMonthPosts
page with HTTP 200 instead of 404, producing unlimited indexable soft-404s and
feeding a cache entry per distinct path.
Constrain year to 4 digits and month to 01-12, mirroring the WordPress
permalink structure the routes were modelled on.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problema
Qualquer caminho de dois segmentos que não case com uma rota anterior é servido como uma página de arquivo vazia com HTTP 200, em vez de 404. O site produz assim um número ilimitado de páginas fantasma indexáveis.
Evidência
Verificado em
https://beta.sourcevortex.com.br/no dia da abertura deste PR:/foo/barYearMonthPosts(vazio)/abcd/efYearMonthPosts(vazio)/9999/99YearMonthPosts(vazio)Todos deveriam ser 404.
Causa
routes/web.phpdeclara as duas rotas de arquivo sem nenhuma restrição de parâmetro:Como estão no fim do arquivo, funcionam como catch-all: qualquer caminho de 2 ou 3 segmentos que não tenha casado antes chega aqui. O controller então executa
que simplesmente não casa nada. A página renderiza vazia e o Laravel responde 200, porque do ponto de vista dele a requisição foi atendida com sucesso.
Três consequências:
WpPostService::getPostsByYearMonth()monta a chave com os valores crus (posts_year_month_foo_bar_page_1) e guarda por um dia. Cada caminho inventado vira uma entrada permanente./wp-admin/...,/assets/...) respondem 200 em vez de 404.Solução
As restrições espelham o permalink do WordPress em que as rotas foram modeladas (
%year%/%monthnum%): ano com 4 dígitos, mês de01a12com zero à esquerda — que é exatamente o queWpPostResourceemite ($date->format('m')).Preferi
0[1-9]|1[0-2]a um[0-9]{2}genérico porque/2026/99continuaria sendo um soft-404 com o segundo.Como validar
Os testes cobrem caminhos não numéricos, meses fora de faixa, meses sem zero à esquerda, anos malformados, as mesmas variações na rota de post, e — importante — que caminhos válidos continuam chegando ao controller.
Verificado nos dois sentidos. Contra o código anterior, todas as asserções de 404 falham:
(500 e não 200 porque no ambiente de teste não existem as tabelas
wp_*; em produção o mesmo caminho responde 200, como na tabela de evidências acima.)Impacto
Nota sobre
phpunit.xmlContém a mesma alteração de duas linhas dos outros PRs desta série (fixar
sqlite/:memory:), sem a qual a suíte não inicia. Se outro PR da série for mesclado primeiro, esta parte vira no-op — o conteúdo é idêntico.Fora de escopo
404.php; aqui o 404 é o padrão do Laravel. Vale um PR próprio.getPostsByYearMonth(). Este PR corta o vetor pela rota, mas a normalização de chaves de cache é tratada no PR de busca.