URLs amigáveis com .htaccess: guia definitivo com caso real de ferramenta WHOIS#
O charme das URLs limpas#
Transformar URLs técnicas como ?d=domain.com&page=wsget em rotas limpas como /tool/whois/info/domain.com/197 não é só estética. Em operação real, isso impacta diretamente a rastreabilidade de logs, CTR orgânico, previsibilidade de roteamento e a manutenção do legado sem quebrar links antigos.
Neste artigo, documento exatamente o procedimento técnico que apliquei para migrar uma ferramenta WHOIS baseada em query string para uma estrutura amigável, mantendo a compatibilidade de parâmetros no backend PHP ($_GET), autoridade de SEO via redirecionamento 301 e boas práticas de segurança e performance.
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/domain.com - rota de informação:
/tool/whois/info/domain.com - rota com identificador:
/tool/whois/info/domain.com/197
Requisitos fundamentais:
- Sem quebrar parâmetros esperados no
index.php. - Sem loop de redirecionamento.
- Sem perda de tráfego indexado das URLs antigas.
- Com fallback estável para casos com ou sem barra final.
2) Diagnóstico técnico: onde o redirecionamento falha#
Antes de escrever as regras no .htaccess, mapeamos os pontos críticos de falha do motor mod_rewrite:
- Ordem de execução: Regras genéricas capturando a requisição antes das regras específicas.
- Conflito de Loop: Mismatch entre redirecionamento externo e rewrite interno.
- Persistência de Parâmetros (Leakage): Parâmetros legados que vazam para a URL final limpa.
- Mutabilidade da QUERY_STRING: Regras anteriores podem reescrever a query string, fazendo com que validações subsequentes falhem.
3) Princípio de desenho: fluxo em duas fases#
A arquitetura que funciona de forma previsível e sem loops divide-se em duas fases independentes:
- Fase 1: Redirecionamentos Externos 301 (Consolidação canônica da URL antiga para a nova).
- Fase 2: Rewrites Internos (Mapeamento transparente da URL nova para o script real
index.php).
4) URLs amigáveis e roteamento interno#
Para capturar o domínio de forma restrita, utilizamos a expressão ([^/]+), que aceita qualquer sequência de caracteres exceto barras, evitando o vazamento de caminhos.
Na rota mais específica (com ID), implementamos a flag [END] do Apache 2.4+. A flag END impede que o mecanismo do mod_rewrite execute sub-requisições e novas passagens pelas regras, cortando loops de redirecionamento interno:
# Rota mais específica primeiro (com ID)
RewriteRule ^tool/whois/info/([^/]+)/([^/]+)/?$ index.php?page=wsget&d=$1&id=$2 [L,QSA,END]
# Rota intermediária (informação)
RewriteRule ^tool/whois/info/([^/]+)/?$ index.php?page=wsinf&d=$1 [L,QSA]
# Rota base (domínio)
RewriteRule ^tool/whois/([^/]+)/?$ index.php?page=whois&d=$1 [L,QSA]
# Rota raiz da ferramenta
RewriteRule ^tool/whois/?$ index.php?page=whois [L,QSA]
5) Redirecionamento 301 seguro com THE_REQUEST e QSD#
Muitas implementações utilizam a variável %{QUERY_STRING} para validar a URL antiga. Contudo, ela é mutável e pode sofrer alterações por outras regras. Para contornar isso, utilizamos a variável de ambiente %{THE_REQUEST}, que contém a linha de requisição HTTP original enviada pelo cliente (ex: GET /tool/whois/?page=wsinf HTTP/1.1) e permanece imutável.
Adicionalmente, em vez de adicionar o caractere ? no fim da URL destino para descartar a query string legada (prática comum em versões antigas do Apache), utilizamos a flag nativa QSD (Query String Discard):
# Redirecionar consulta com ID antigo para rota limpa
RewriteCond %{THE_REQUEST} \s/tool/whois/info/([^/]+)/?\?page=wsget&id=([^&\s]+) [NC]
RewriteRule ^tool/whois/info/([^/]+)/?$ tool/whois/info/$1/%2 [R=301,L,QSD]
# Redirecionar página de informação legada
RewriteCond %{THE_REQUEST} \s/tool/whois/\?([^&\s]+)&page=wsinf [NC]
RewriteRule ^tool/whois/?$ tool/whois/info/%1 [R=301,L,QSD]
6) Arquivo .htaccess de produção completo#
# ====================================================================
# .htaccess - Configuração de Roteamento de URLs Amigáveis (WHOIS)
# ====================================================================
RewriteEngine On
RewriteBase /
# 1. SEGURANÇA E BARRAS
# Bloqueia listagem de diretórios
Options -Indexes
# Página de Erro 404 Customizada
ErrorDocument 404 /404.php
# Bloqueia leitura de arquivos sensíveis
RewriteRule ^(\.git|\.env|composer\.json) - [F,L]
# Força HTTPS (considerando proxies/load balancers)
RewriteCond %{HTTP:X-Forwarded-Proto} !https
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}/$1 [R=301,L]
# Normalização de Trailing Slash (Adiciona barra apenas para diretórios reais)
RewriteCond %{REQUEST_FILENAME} -d
RewriteCond %{REQUEST_URI} !(.*)/$
RewriteRule ^(.*)$ $1/ [R=301,L]
# Normalização de Trailing Slash (Remove barra final de caminhos virtuais)
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.+)/$ /$1 [R=301,L]
# 2. FASE 1: REDIRECIONAMENTOS 301 CANÔNICOS (Legado -> Novo)
RewriteCond %{THE_REQUEST} \s/tool/whois/info/([^/]+)/?\?page=wsget&id=([^&\s]+) [NC]
RewriteRule ^tool/whois/info/([^/]+)/?$ tool/whois/info/$1/%2 [R=301,L,QSD]
RewriteCond %{THE_REQUEST} \s/tool/whois/\?([^&\s]+)&page=wsinf [NC]
RewriteRule ^tool/whois/?$ tool/whois/info/%1 [R=301,L,QSD]
# 3. FASE 2: REWRITE INTERNO (Roteamento transparente para index.php)
RewriteRule ^tool/whois/info/([^/]+)/([^/]+)/?$ index.php?page=wsget&d=$1&id=$2 [L,QSA,END]
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) Depuração de regras e logs no servidor#
Se alguma regra se comportar de maneira inesperada, você deve ativar o log de rewrites no arquivo de configuração do VirtualHost do Apache (não permitido diretamente no .htaccess):
# Configuração de Logs do mod_rewrite no Apache 2.4+
LogLevel alert rewrite:trace3
Os níveis de trace vão de trace1 a trace9 (sendo trace3 suficiente para a maioria dos testes sem sobrecarregar o I/O do disco em homologação).
Teste de regex e CLI#
- Validação Sintática: Antes de reiniciar o servidor, verifique a sintaxe com
apache2ctl -touhttpd -t. - Validação do mod_rewrite: Para listar as regras ativas compiladas no host, use:
apache2ctl -t -D DUMP_REWRITE_RULES
- Simulador Online: Utilize o RegEx101 configurado em modo PCRE para testar seus grupos de captura.
8) Considerações de performance (vhosts vs .htaccess)#
O uso de arquivos .htaccess introduz latência em servidores Apache de alta carga. Isso ocorre porque o Apache é obrigado a escanear e parsear o arquivo .htaccess recursivamente em cada diretório a cada requisição de arquivo.
Boa prática de escala: Se você possui acesso root ao servidor, desabilite o .htaccess definindo AllowOverride None e mova todas as regras de reescrita diretamente para o bloco do seu VirtualHost no httpd.conf ou apache2.conf. Isso mantém as regras compiladas na memória do processo e elimina a leitura de disco.
RewriteBase - quando usar e quando evitar#
Quando o .htaccess está na raiz do domínio (/), a diretiva RewriteBase / é redundante - o Apache já assume / como base implícita. Incluí-la na raiz não causa problemas, mas não adiciona valor.
Em subdiretórios (ex: .htaccess em /tool/), omitir RewriteBase pode causar comportamento incorreto: o Apache avaliará os padrões RewriteRule relativos ao caminho completo da URL, ignorando o prefixo do subdiretório. Nesses casos, declare explicitamente:
# .htaccess em /tool/whois/
RewriteBase /tool/whois/
FollowSymLinks e SymLinksIfOwnerMatch#
A opção Options +FollowSymLinks é frequentemente necessária para o mod_rewrite funcionar. Porém, ela elimina a proteção contra ataques de symlink, onde um usuário mal-intencionado em servidor compartilhado pode criar um link simbólico para arquivos de outro usuário.
Options +SymLinksIfOwnerMatch é a alternativa mais segura: permite seguir symlinks apenas se o link e o destino pertencem ao mesmo dono. O custo é uma chamada extra ao sistema (lstat()), adicionando latência mínima por requisição.
# Em servidores compartilhados: prefira SymLinksIfOwnerMatch
Options +SymLinksIfOwnerMatch
# Em servidores dedicados com controle total: FollowSymLinks é suficiente
# Options +FollowSymLinks
9) Referência de flags do RewriteRule#
| Flag | Descrição | Cenário de Uso |
|---|---|---|
[L] (Last) | Interrompe o processamento na passagem atual. | Regras de reescrita interna. |
[END] | Bloqueia todas as passagens subsequentes de reescrita. | Evitar loops infinitos de sub-rotas. |
[R=301] | Emite um redirecionamento HTTP permanente. | SEO, migração de links e caminhos. |
[QSA] | Adiciona query strings novas à query string reescrita. | Preservar filtros extras via URL. |
[QSD] | Descarta a query string original na rota final. | Limpeza de parâmetros antigos em redirects. |
[NC] | Ignora diferenciação de maiúsculas/minúsculas. | Match robusto de caminhos. |
[F] | Retorna erro HTTP 403 Forbidden. | Bloqueio de arquivos sensíveis. |
10) Prevenção de split de pagerank durante a migração#
Durante o período de migração - enquanto as URLs legadas com query string ainda estão indexadas e sendo rastreadas pelo Googlebot - existe o risco de split de PageRank: o rastreador pode tratar a URL antiga e a nova como conteúdos duplicados e dividir a autoridade de link entre elas, mesmo com o redirecionamento 301 no lugar.
Para mitigar isso, sinalize explicitamente às URLs canônicas com query string que elas não devem ser indexadas durante a transição:
# Adicionar no VirtualHost ou no .htaccess, após o bloco de segurança
# Sinaliza ao Googlebot para não indexar URLs com parâmetros legados
<If "%{QUERY_STRING} =~ /page=ws(get|inf|hois)/">
Header always set X-Robots-Tag "noindex, nofollow"
</If>
Considerações práticas#
A migração para URLs amigáveis em Apache exige controle fino de regex, ordem de processamento e canonicidade. Ao utilizar THE_REQUEST para isolar requisições originais, a flag QSD para limpeza e a flag END para evitar loops de processamento, você garante um roteamento rápido, robusto e perfeitamente otimizado para os rastreadores de SEO e segurança do host.
Este artigo foi útil?
Deixe uma reação rápida para apoiar o conteúdo:
Este post está licenciado sob CC BY-NC.


Comentários
Participe da discussão abaixo.
0 comentários