URLs amigáveis com .htaccess: guia definitivo com caso real de ferramenta WHOIS
Voltar para blog

URLs amigáveis com .htaccess: guia definitivo com caso real de ferramenta WHOIS

07/06/2026 · 6 min · Infraestrutura

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:

  1. rota base de domínio: /tool/whois/domain.com
  2. rota de informação: /tool/whois/info/domain.com
  3. rota com identificador: /tool/whois/info/domain.com/197

Requisitos fundamentais:


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:

  1. Ordem de execução: Regras genéricas capturando a requisição antes das regras específicas.
  2. Conflito de Loop: Mismatch entre redirecionamento externo e rewrite interno.
  3. Persistência de Parâmetros (Leakage): Parâmetros legados que vazam para a URL final limpa.
  4. 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:

  1. Fase 1: Redirecionamentos Externos 301 (Consolidação canônica da URL antiga para a nova).
  2. Fase 2: Rewrites Internos (Mapeamento transparente da URL nova para o script real index.php).
flowchart LR CLIENT(["🌐 Browser\nGET /tool/whois/?d=x"]) --> APACHE["Apache\nmod_rewrite"] APACHE --> F1{"Fase 1:\nRedirecionamento\n301 Canônico?"} F1 -->|"URL legada\ndetectada via\nTHE_REQUEST"| REDIR["HTTP 301\n→ /tool/whois/info/x"] REDIR -->|"Nova requisição\ndo browser"| APACHE F1 -->|"URL já limpa"| F2{"Fase 2:\nRewrite\nInterno?"} F2 -->|"Match da rota"| PHP["index.php\n?page=wsget&d=x&id=y"] F2 -->|"Sem match"| FS["Arquivo/Diretório\nreal no disco"] PHP --> RESP(["HTTP 200\nResposta PHP"]) FS --> RESP style REDIR fill:#78350f,color:#fde68a style PHP fill:#14532d,color:#86efac style F1 fill:#1e3a5f,color:#93c5fd style F2 fill:#1e3a5f,color:#93c5fd

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#

  apache2ctl -t -D DUMP_REWRITE_RULES

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/

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#

FlagDescriçãoCená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:

CC BY-NC

Este post está licenciado sob CC BY-NC.

Comentários

Participe da discussão abaixo.

0 comentários