No seguimento deste post, relembro o exemplo que dei do jornal Público: http://www.publico.clix.pt/Sociedade/divulgacao-de-escutas-na-internet-punivel-pela-lei-do-cibercrime_1419063. Acho que é claro para todos que não existe, no site do jornal Público, nenhum directório “Sociedade” e muito menos um directório para cada notícia que eles colocam.
Na realidade, o que acontece é um redireccionamento invisível do pedido para um script central que, neste caso, trata das notícias. Esse redireccionamento é feito com a extensão mod_rewrite do Apache. O mod_rewrite é uma espécie de pau para toda a obra dos redireccionamentos, desde visíveis a invisíveis, com inúmeras aplicações.
Por exemplo, uma das aplicações mais simples serve para redireccionar, de forma visível, de um domínio para outro. Aqui no DreamsInCode, por exemplo, é possível aceder ao site por http://www.dreamsincode.com, assim como por http://dreamsincode.com. Por várias razões, eu quero forçar que a entrada seja sempre pelo domínio completo, com www. Esse objectivo é conseguido colocando o seguinte código num ficheiro .htaccess na raíz do site:
<IfModule mod_rewrite.c> RewriteEngine On RewriteCond %{HTTP_HOST} ^dreamsincode\.com$ [NC] RewriteRule ^(.*)$ http://www.dreamsincode.com/$1 [R=301,L] </IfModule>
As instruções IfModule
servem para verificar se o módulo foi compilado com o Apache. Na falta destas instruções e no caso da extensão não estar carregada, o mais provável seria ficarem a olhar para uma página de erro, 500 Internal Server Error. Depois de se ligar a extensão, via RewriteEngine On
, vêm as condições com RewriteCond
: em primeiro lugar aquilo que queremos comparar, neste caso HTTP_HOST
, uma expressão regular e finalmente um conjunto de modificadores. O modificador que estou a usar neste exemplo é o NC, que indica que a comparação deve ser feita ignorando a capitalização.
Finalmente, temos a regra de redireccionamento, RewriteRule
: primeiro apanhamos, com uma expressão regular, tudo o que está no endereço para além do domínio e depois dizemos exactamente como queremos reescrever o caminho – o $1
indica que é para colocar tudo o que apanhamos antes a seguir ao novo domínio. O modificador R indica que é um redireccionamento visível, com o respectivo código a devolver ao browser (neste caso, 301 Moved Permanently) e o L indica que é a última regra deste bloco.
Voltando ao nosso problema inicial, o que nós queremos não é um redireccionamento visível, mas sim invisível. Uma possível solução para o caso do Público seria a seguinte:
<IfModule mod_rewrite.c> RewriteEngine On RewriteRule ^([a-z0-9-]+)/?$ index.php?action=getNoticiasCategoria&nome_categoria=$1 RewriteRule ^([a-z0-9-]+)/([a-z0-9-]+)/?$ index.php?action=getNoticia&nome_categoria=$1&nome_noticia=$2 [L] </IfModule>
Reparem como não existem condições, isto é, tudo o que vier por aqui no formato correcto é automaticamente apanhado. As expressões regulares ditam que é para apanhar qualquer coisa que contenha letras, números e hífens. A primeira regra é executada se vier apenas um directório no URL (por exemplo, http://www.publico.clix.pt/Sociedade/) e a segunda se vierem dois, que é o nosso exemplo inicial. O pedido é então reencaminhado para um script, com parâmetros diferentes, que devolve o que é necessário de forma opaca para o browser, que continua a mostrar o endereço pedido – reparem como nenhuma das regras tem o modificador R.
Para finalizar, enquanto escrevia estes dois posts encontrei uma cheat sheet (uma folha de copianço) para o mod_rewrite muito boa. Aliás, existem várias cheat sheets para diversas coisas nesse site, assim como vários artigos interessantes.
Actualização 2017: Enviaram-me esta cheat sheet um pouco mais profunda.