Transformar URLs técnicas como ?d=exemplo.com&page=wsget em rotas limpas como /tool/whois/info/exemplo.com/197 não é só estética. Em operação real, isso impacta diretamente rastreabilidade de logs, CTR orgânico, previsibilidade de roteamento e manutenção do legado sem quebrar links antigos.
Neste artigo, documento exatamente o procedimento que apliquei para migrar uma ferramenta WHOIS baseada em query string para uma estrutura amigável, mantendo compatibilidade de parâmetros no backend PHP ($_GET) e autoridade SEO via redirecionamento 301.
1) Problema inicial: query string funcional, mas ruim para SEO e operação
URL antiga:
https://exemplo.com/tool/whois/?d=dominio1.com
Arquitetura alvo definida:
- rota base de domínio:
/tool/whois/dominio1.com
- rota de informação:
/tool/whois/info/dominio2.com
- rota com identificador:
/tool/whois/info/dominio3.com/197
Requisitos que precisei manter:
- sem quebrar parâmetros esperados no
index.php - sem loop de redirecionamento
- sem perda de tráfego indexado de URLs antigas
- com fallback estável para casos sem barra final
2) Diagnóstico técnico: onde normalmente quebra
Antes de escrever regras, validei os pontos críticos do mod_rewrite:
- ordem de execução (regra genérica capturando antes da específica)
- conflito entre redirecionamento externo e rewrite interno
- persistência indevida de query string antiga após 301
- regex permissiva demais gerando match errado
Comando de validação local do Apache:
apachectl -t
E, em ambiente com vhost separado:
httpd -t
3) Princípio de desenho aplicado
A estrutura que funcionou de forma previsível foi:
- primeiro: redirecionamentos externos 301 (URL antiga -> URL nova)
- depois: rewrites internos (URL nova ->
index.php?page=...)
Esse desenho evita duas falhas clássicas:
- URL antiga cair direto no rewrite interno sem consolidar canônico
- regra interna capturar requisição que deveria sofrer redirect
4) Regras de rewrite interno por rota
Para captura do domínio, usei ([^/]+), que aceita qualquer sequência sem barra e evita “vazamento” para outros segmentos.
RewriteRule ^tool/whois/([^/]+)/?$ index.php?page=whois&d=$1 [L,QSA]
Regras completas internas usadas no caso:
# Rota com ID
RewriteRule ^tool/whois/info/([^/]+)/([^/]+)/?$ index.php?page=wsget&d=$1&id=$2 [L,QSA]
# Rota de informacao
RewriteRule ^tool/whois/info/([^/]+)/?$ index.php?page=wsinf&d=$1 [L,QSA]
# Rota base da ferramenta
RewriteRule ^tool/whois/?$ index.php?page=whois [L,QSA]
5) Redirecionamento 301 de legado com limpeza de query string
No legado, havia chamadas com page=wsinf e variações com parâmetros na query string. Para consolidar SEO, apliquei 301 antes do rewrite interno.
Regra aplicada:
RewriteCond %{QUERY_STRING} ^([^&]+)&page=wsinf$ [NC]
RewriteRule ^tool/whois/?$ tool/whois/info/%1? [R=301,L]
Ponto-chave: o ? no fim da URL de destino descarta a query string antiga. Sem isso, o navegador mantém parâmetros legados e polui URL final.
6) Arquivo .htaccess final (versão de produção)
RewriteEngine On
RewriteBase /
# 1) REDIRECIONAMENTOS 301 (legado -> novo padrão)
RewriteCond %{QUERY_STRING} ^page=wsget&id=([^&]+)$ [NC]
RewriteRule ^tool/whois/info/([^/]+)/?$ tool/whois/info/$1/%1? [R=301,L]
RewriteCond %{QUERY_STRING} ^([^&]+)&page=wsinf$ [NC]
RewriteRule ^tool/whois/?$ tool/whois/info/%1? [R=301,L]
# 2) REWRITE INTERNO (roteamento para index.php)
RewriteRule ^tool/whois/info/([^/]+)/([^/]+)/?$ index.php?page=wsget&d=$1&id=$2 [L,QSA]
RewriteRule ^tool/whois/info/([^/]+)/?$ index.php?page=wsinf&d=$1 [L,QSA]
RewriteRule ^tool/whois/([^/]+)/?$ index.php?page=whois&d=$1 [L,QSA]
RewriteRule ^tool/whois/?$ index.php?page=whois [L,QSA]
7) Validação em campo (sem suposição)
Após publicar regras, executei bateria objetiva de testes:
- validar sintaxe Apache:
apachectl -t
- validar rota final com headers HTTP:
curl -I "https://exemplo.com/tool/whois/?dominio1.com&page=wsinf"
curl -I "https://exemplo.com/tool/whois/info/dominio1.com"
- validar aplicação recebendo parâmetros corretos:
$_GET['page']$_GET['d']$_GET['id']
- validar ausência de loop:
curl -IL "https://exemplo.com/tool/whois/?dominio1.com&page=wsinf"
- validar canônico com e sem slash final:
/tool/whois/info/dominio.com/tool/whois/info/dominio.com/
8) Troubleshooting que precisei fazer
8.1 Regra genérica capturando antes da específica
Sintoma:
- rota com ID caindo na rota sem ID
Correção:
- ordenar regras da mais específica para a mais genérica
8.2 Browser cache mascarando erro
Sintoma:
- parecia que regra nova não funcionava
Causa:
- 301 em cache local do navegador
Correção operacional:
- teste em aba anônima
- teste com
curl -I/-L
8.3 Query string reaparecendo após redirect
Sintoma:
- URL final com parâmetros antigos
Correção:
- adicionar
?no destino doRewriteRule301
9) Boas práticas consolidadas
- usar
[NC]em comparações de query string sensíveis a case - usar
/?$quando quiser tolerar barra final - separar claramente redirect (externo) de rewrite (interno)
- validar com
curle log de acesso, não apenas pelo navegador - documentar matriz de rotas para evitar regressão em manutenção futura
Conclusão técnica
A migração para URLs amigáveis em Apache exige controle fino de regex, ordem de processamento e canonicidade. Com o .htaccess estruturado em duas fases (redirect 301 + rewrite interno), consegui preservar compatibilidade legada, melhorar SEO e manter o backend PHP operando com os mesmos parâmetros de negócio.
Não foi uma troca cosmética de URL. Foi uma refatoração de roteamento com governança de tráfego e estabilidade de aplicação.
Este post está licenciado sob CC BY-NC.
Comentários
Participe da discussão abaixo.
Comentários ainda não configurados. Adicione as opções do Cusdis em /assets/json/config/blog-comments-config.json.