Parece haver um número decente de mod_rewrite
threads flutuando ultimamente com um pouco de confusão sobre como certos aspectos dele funcionam. Como resultado, compilei algumas notas sobre funcionalidades comuns e talvez algumas nuances irritantes.
Quais outros recursos / problemas comuns você já encontrou mod_rewrite
?
apache
.htaccess
mod-rewrite
Owen
fonte
fonte
Respostas:
Onde colocar regras mod_rewrite
mod_rewrite
regras podem ser colocadas dentro dohttpd.conf
arquivo ou dentro dele.htaccess
. se você tiver acessohttpd.conf
, a colocação de regras aqui oferecerá um benefício de desempenho (como as regras são processadas uma vez, ao contrário de cada vez que o.htaccess
arquivo é chamado).Registrando solicitações mod_rewrite
O log pode ser ativado de dentro do
httpd.conf
arquivo (incluindo<Virtual Host>
):Casos de uso comuns
Para canalizar todas as solicitações para um único ponto:
Desde o Apache 2.2.16, você também pode usar
FallbackResource
.Manipulando redirecionamentos 301/302:
Nota : redirecionamentos externos são implicitamente redirecionamentos 302:
Forçando SSL
Sinalizadores comuns:
[R]
ou[redirect]
- forçar um redirecionamento (o padrão é um redirecionamento 302 temporário)[R=301]
ou[redirect=301]
- forçar um redirecionamento permanente 301[L]
ou[last]
- interrompa o processo de reescrita (veja a nota abaixo em armadilhas comuns)[NC]
ou[nocase]
- especificar que a correspondência não diferencia maiúsculas de minúsculasO uso da forma longa de sinalizadores geralmente é mais legível e ajudará outras pessoas que vierem a ler seu código posteriormente.
Você pode separar vários sinalizadores com uma vírgula:
Armadilhas comuns
Misturando
mod_alias
redirecionamentos de estilo commod_rewrite
Nota : você pode misturar
mod_alias
commod_rewrite
, mas envolve mais trabalho do que apenas lidar com redirecionamentos básicas como acima.O contexto afeta a sintaxe
Nos
.htaccess
arquivos, uma barra inicial não é usada no padrão RewriteRule:[L] não é o último! (as vezes)
O
[L]
sinalizador interrompe o processamento de quaisquer regras de reescrita adicionais para essa passagem pelo conjunto de regras . No entanto, se o URL foi modificado nessa passagem e você estiver no.htaccess
contexto ou na<Directory>
seção, sua solicitação modificada será transmitida novamente pelo mecanismo de análise de URL novamente. E no próximo passe, pode corresponder a uma regra diferente dessa vez. Se você não entende isso, muitas vezes parece que sua[L]
bandeira não teve efeito.Nosso log de reescrita mostra que as regras são executadas duas vezes e a URL é atualizada duas vezes:
A melhor maneira de contornar isso é usar o
[END]
sinalizador ( consulte a documentação do Apache ) em vez do[L]
sinalizador, se você realmente deseja interromper todo o processamento adicional de regras (e passes subsequentes). No entanto, a[END]
sinalização está disponível apenas para o Apache v2.3.9 + ; portanto, se você tiver a v2.2 ou inferior, ficará com apenas a[L]
sinalização.Para versões anteriores, você deve confiar nas
RewriteCond
instruções para impedir a correspondência de regras nas passagens subsequentes do mecanismo de análise de URL.Ou você deve garantir que suas RewriteRule estejam em um contexto (ou seja
httpd.conf
) que não fará com que sua solicitação seja analisada novamente.fonte
[L]
sinalizador significa que uma regra é a última no processamento atual; isso não interrompe a reescrita, porque são redirecionamentos internos; portanto, vocêdirB
aplica-se aodirC
próximo processamento htaccess. Sozinho,RewriteRule ^(.*)$ index.php?query=$1
haverá um loop infinito de redirecionamentos internos (na prática, é encerrado após 10 iterações). -1 porque você sugere que [L] não é o último . Não está encerrando o processo de reescrita, mas é o último .RewriteCond %{HTTPS} off
é a forma preferida para verificar se há uma conexão HTTPS (no seu exemplo de forçar o tráfego não-SSL para HTTPS)se você precisar "bloquear" redirecionamentos / reescritos internos no arquivo .htaccess, consulte o
condição, conforme discutido aqui .
fonte
.*
a[L]
bandeira que li antes de chegar aqui.200
,!=200
,^.
,^$
. Aparentemente, a variável é definida como200
redirecionada, mas também outras páginas (erro e outras coisas) definem-na para algum valor. Agora isso significa que você quer verificar se eleis empty
,is not empty
,is 200
ouis not 200
, dependendo do que você precisa.O acordo com RewriteBase:
Você quase sempre precisa definir o RewriteBase. Caso contrário, o apache acha que sua base é o caminho do disco físico para o seu diretório. Então comece com isso:
fonte
RewriteBase .
ou algo para indicar que ele deve manter o URL igual, apenas alterando o que você especificou?RewriteBase
se estiver usando a substituição de caminho relativo naRewriteRule
diretiva. É melhor evitar o uso de caminhos relativos.RewriteBase
completamente, pois quase todos os desenvolvedores não entendem o que fazem. Como o @ w3d disse, você só precisa se deseja salvar caracteres e aplicar a mesma base a todas as suas RewriteRules em um arquivo. Seu código provavelmente será mais claro para os outros se você evitá-lo.Outras armadilhas:
1- Às vezes, é uma boa ideia desabilitar o MultiViews
Não sou versado em todos os recursos do MultiViews, mas sei que ele atrapalha minhas regras mod_rewrite quando ativo, porque uma de suas propriedades é tentar 'adivinhar' uma extensão de um arquivo que ele procura. .
Vou explicar: suponha que você tenha 2 arquivos php em seu diretório da web, file1.php e file2.php e adicione essas condições e regra ao seu .htaccess:
Você assume que todos os URLs que não correspondem a um arquivo ou diretório serão capturados por file1.php. Surpresa! Esta regra não está sendo respeitada pelo URL http: // myhost / file2 / somepath . Em vez disso, você é levado para dentro do arquivo2.php.
O que está acontecendo é que o MultiViews adivinhou automaticamente que o URL que você realmente queria era http: //myhost/file2.php/somepath e com prazer o levou até lá.
Agora, você não tem idéia do que aconteceu e, nesse momento, está questionando tudo o que achou que sabia sobre o mod_rewrite. Você começa a brincar com as regras para tentar entender a lógica por trás dessa nova situação, mas quanto mais testando, menos sentido faz.
Ok, resumindo, se você deseja que o mod_rewrite funcione de maneira que se aproxime da lógica, desativar o MultiViews é um passo na direção certa.
2- ativar o FollowSymlinks
Na verdade, eu não conheço os detalhes, mas já o vi mencionado muitas vezes, então faça isso.
fonte
+FollowSymLinks
é mencionado na documentação como obrigatório para omod_rewrite
trabalho, por vagas razões de segurança.A equação pode ser feita com o seguinte exemplo:
Balanceamento de carga dinâmico:
Se você usar o mod_proxy para equilibrar seu sistema, é possível adicionar um intervalo dinâmico de servidor de trabalho.
fonte
Uma melhor compreensão da bandeira [L] está em ordem. O sinalizador [L] é o último, você apenas precisa entender o que fará com que sua solicitação seja roteada pelo mecanismo de análise de URL novamente. Dos documentos ( http://httpd.apache.org/docs/2.2/rewrite/flags.html#flag_l ) (ênfase minha):
Assim, o [L] bandeira faz parar o processamento de quaisquer regras adicionais de reescrita para que passe através do conjunto de regras. No entanto, se sua regra marcada com [L] modificou a solicitação e você está no contexto .htaccess ou na
<Directory>
seção, sua solicitação modificada será passada de volta pelo mecanismo de análise de URL novamente. E no próximo passe, pode corresponder a uma regra diferente dessa vez. Se você não entender o que aconteceu, parece que sua primeira regra de reescrita com o sinalizador [L] não teve efeito.A melhor maneira de contornar isso é usar o sinalizador [END] ( http://httpd.apache.org/docs/current/rewrite/flags.html#flag_end ) em vez do sinalizador [L], se você realmente deseja parar todo o processamento adicional de regras (e subsequente nova correção). No entanto, o sinalizador [END] está disponível apenas para o Apache v2.3.9 +; portanto, se você tiver o v2.2 ou inferior, ficará com apenas o sinalizador [L]. Nesse caso, você deve confiar nas instruções RewriteCond para impedir a correspondência de regras nas passagens subsequentes do mecanismo de análise de URL. Ou você deve garantir que suas RewriteRule estejam em um contexto (por exemplo, httpd.conf) que não fará com que sua solicitação seja analisada novamente.
fonte
Outro ótimo recurso são reescrever-mapa-expansões. Eles são especialmente úteis se você tiver uma grande quantidade de hosts / reescritas para lidar com:
Eles são como uma substituição de valor-chave:
Então você pode usar um mapeamento em suas regras como:
Mais informações sobre este tópico podem ser encontradas aqui:
http://httpd.apache.org/docs/2.0/mod/mod_rewrite.html#mapfunc
fonte
.htaccess
reescritas com base. Não funciona neste contexto.mod_rewrite pode modificar aspectos do tratamento de solicitações sem alterar a URL, por exemplo, definindo variáveis de ambiente, definindo cookies, etc. Isso é incrivelmente útil.
Defina condicionalmente uma variável de ambiente:
Retornar uma resposta 503:
RewriteRule
o[R]
sinalizador pode pegar um valor que não seja 3xx e retornar uma resposta que não redireciona, por exemplo, para tempo de inatividade / manutenção gerenciados:retornará uma resposta 503 (não um redirecionamento em si).
Além disso, mod_rewrite pode atuar como uma interface superpoderosa para mod_proxy, para que você possa fazer isso em vez de escrever
ProxyPass
diretivas:Opinião: Usar
RewriteRule
s eRewriteCond
s para rotear solicitações para diferentes aplicativos ou balanceadores de carga com base em praticamente qualquer aspecto concebível da solicitação é imensamente poderoso. Controlar solicitações no caminho para o back-end e poder modificar as respostas no caminho de volta faz do mod_rewrite o local ideal para centralizar toda a configuração relacionada ao roteamento.Aproveite o tempo para aprender, vale a pena! :)
fonte