Esta é uma pergunta canônica sobre o mod_rewrite do Apache.
A alteração de um URL de solicitação ou o redirecionamento de usuários para um URL diferente daquele solicitado originalmente é feito com o mod_rewrite. Isso inclui coisas como:
- Alterando HTTP para HTTPS (ou o contrário)
- Alterando uma solicitação para uma página que não existe mais para uma nova substituição.
- Modificando um formato de URL (como? Id = 3433 para / id / 3433)
- Apresentar uma página diferente com base no navegador, com base no referenciador, com base em qualquer coisa possível sob a lua e o sol.
- Tudo o que você quiser mexer com o URL
Tudo o que você sempre quis saber sobre as regras do Mod_Rewrite, mas teve medo de perguntar!
Como posso me tornar um especialista em escrever regras mod_rewrite?
- Qual é o formato e a estrutura fundamentais das regras mod_rewrite?
- De que forma / sabor das expressões regulares eu preciso ter uma sólida compreensão?
- Quais são os erros / armadilhas mais comuns ao escrever regras de reescrita?
- Qual é um bom método para testar e verificar regras mod_rewrite?
- Existem implicações de SEO ou desempenho das regras mod_rewrite das quais devo estar ciente?
- Existem situações comuns em que mod_rewrite pode parecer a ferramenta certa para o trabalho, mas não é?
- Quais são alguns exemplos comuns?
Um lugar para testar suas regras
O site do testador de htaccess é um ótimo lugar para brincar com suas regras e testá-las. Ele até mostra a saída de depuração para que você possa ver o que correspondeu e o que não correspondeu.
apache-2.2
mod-rewrite
redirect
redirection
301-redirect
Kyle Brandt
fonte
fonte
mod-rewrite
pesquisas / filtros de tags.Respostas:
ordem de sintaxe mod_rewrite
mod_rewrite possui algumas regras de pedidos específicas que afetam o processamento. Antes que qualquer coisa seja feita, a
RewriteEngine On
diretiva precisa ser fornecida, pois isso ativa o processamento mod_rewrite. Isso deve ocorrer antes de qualquer outra diretiva de reescrita.RewriteCond
anteriorRewriteRule
torna essa regra sujeita à condicional. Quaisquer RewriteRules a seguir serão processadas como se não estivessem sujeitas a condicionais.Nesse caso simples, se o referenciador HTTP for de serverfault.com, redirecione as solicitações de blog para páginas especiais de falha do servidor (somos tão especiais assim). No entanto, se o bloco acima tiver uma linha RewriteRule extra:
Todos os arquivos .jpg iriam para as páginas especiais de falha do servidor, não apenas aquelas com um referenciador indicando que ele veio daqui. Claramente, essa não é a intenção de como essas regras são escritas. Isso pode ser feito com várias regras RewriteCond:
Mas provavelmente deve ser feito com alguma sintaxe de substituição mais complicada.
O RewriteRule mais complexo contém os condicionais para processamento. O último parênteses,
(html|jpg)
diz ao RewriteRule para corresponder a umhtml
oujpg
, e para representar a sequência correspondente como $ 2 na sequência reescrita. Isso é logicamente idêntico ao bloco anterior, com dois pares RewriteCond / RewriteRule, apenas o faz em duas linhas, em vez de quatro.Várias linhas RewriteCond são implicitamente ANDed e podem ser explicitamente ORed. Para manipular referenciadores do ServerFault e do Superusuário (OR explícito):
Para veicular as páginas referidas ServerFault nos navegadores Chrome (AND implícito):
RewriteBase
também é específico do pedido, pois especifica como asRewriteRule
diretivas a seguir lidam com o processamento. É muito útil em arquivos .htaccess. Se usada, deve ser a primeira diretiva em "RewriteEngine on" em um arquivo .htaccess. Veja este exemplo:Isso está dizendo ao mod_rewrite que esse URL específico que ele está manipulando chegou por meio de http://example.com/blog/ em vez do caminho do diretório físico (/ home / $ Username / public_html / blog) e para tratá-lo adequadamente. Por isso,
RewriteRule
considera que o início da cadeia de caracteres está após o "/ blog" no URL. Aqui está a mesma coisa escrita de duas maneiras diferentes. Um com RewriteBase, o outro sem:Como você pode ver,
RewriteBase
permite reescrever regras para aproveitar o caminho do conteúdo do site em vez do servidor da web , o que pode torná-las mais inteligíveis para quem edita esses arquivos. Além disso, eles podem reduzir as diretrizes, o que tem um apelo estético.Sintaxe de correspondência RewriteRule
O próprio RewriteRule possui uma sintaxe complexa para seqüências de caracteres correspondentes. Vou cobrir as bandeiras (coisas como [PT]) em outra seção. Como os administradores de sistemas aprendem pelo exemplo com mais frequência do que lendo uma página de manual, darei exemplos e explicarei o que eles fazem.
A
.*
construção corresponde a qualquer caractere único (.
) zero ou mais vezes (*
). Colocá-lo entre parênteses indica que você forneça a sequência que correspondeu à variável $ 1.Nesse caso, o primeiro. * NÃO foi colocado entre parênteses, portanto, não é fornecido para a sequência reescrita. Esta regra remove um nível de diretório no novo site do blog. (/blog/2009/sample.html se torna /newblog/sample.html).
Nesse caso, a primeira expressão entre parênteses configura um grupo correspondente. Isso se torna $ 1, o que não é necessário e, portanto, não é usado na string reescrita.
Nesse caso, usamos $ 1 na string reescrita.
Esta regra usa uma sintaxe de colchete especial que especifica um intervalo de caracteres . [0-9] corresponde aos números de 0 a 9. Esta regra específica tratará os anos de 2000 a 2099.
Isso faz o mesmo que a regra anterior, mas a parte {2} diz para ele corresponder ao caractere anterior (uma expressão de colchete nesse caso) duas vezes.
Esse caso corresponderá a qualquer letra minúscula na segunda expressão correspondente e o fará com o máximo de caracteres possível. A
\.
construção diz para tratar o período como um período real, não como o caractere especial nos exemplos anteriores. Ele será interrompido se o nome do arquivo contiver traços.Isso intercepta nomes de arquivos com traços neles. No entanto, como
-
é um caractere especial nas expressões entre colchetes, ele deve ser o primeiro caractere na expressão.Esta versão captura qualquer nome de arquivo com letras, números ou o
-
caractere no nome do arquivo. É assim que você especifica vários conjuntos de caracteres em uma expressão entre colchetes.Sinalizadores RewriteRule
As bandeiras nas regras de reescrita têm vários significados e casos especiais .
A bandeira está
[L]
no final da expressão acima. Vários sinalizadores podem ser usados, separados por vírgula. A documentação vinculada descreve cada uma, mas aqui estão elas de qualquer maneira:L = Último. Pare de processar RewriteRules quando este corresponder. A ordem conta!
C = Cadeia. Continue processando a próxima RewriteRule. Se essa regra não corresponder, a próxima regra não será executada. Mais sobre isso mais tarde.
E = Definir variável ambiental. O Apache possui várias variáveis ambientais que podem afetar o comportamento do servidor da web.
F = Proibido. Retorna um erro proibido 403 se esta regra corresponder.
G = Se foi. Retorna um erro 410-Gone se esta regra corresponder.
H = manipulador. Força a solicitação a ser tratada como se fosse o tipo MIME especificado.
N = Avançar. Força a regra a recomeçar e corresponder. SEJA CUIDADOSO! Loops podem resultar.
NC = Sem caso. Permite
jpg
para corresponder a jpg e JPG.NE = Sem escapatória. Impede a reescrita de caracteres especiais (.? # & Etc) em seus equivalentes de código hexadecimal.
NS = Nenhuma sub-solicitação. Se você estiver usando inclusões do lado do servidor, isso impedirá correspondências com os arquivos incluídos.
P = Proxy. Força a regra a ser manipulada por mod_proxy. Forneça de forma transparente o conteúdo de outros servidores, porque o seu servidor da Web o busca e serve novamente. Esta é uma bandeira perigosa, uma vez que uma mensagem mal escrita transformará seu servidor da Web em um proxy aberto e Isso é Ruim.
PT = Passagem Completa. Leve em conta as instruções de alias na correspondência RewriteRule.
QSA = QSAppend. Quando a string original contém uma consulta ( http://example.com/thing?asp=foo) anexa a string de consulta original à string reescrita. Normalmente seria descartado. Importante para conteúdo dinâmico.
R = Redirecionar. Forneça um redirecionamento HTTP para o URL especificado. Também pode fornecer código de redirecionamento exato [R = 303]. Muito parecido com o
RedirectMatch
que é mais rápido e deve ser usado quando possível.S = Ignorar. Pule esta regra.
T = tipo. Especifique o tipo MIME do conteúdo retornado. Muito parecido com a
AddType
diretiva.Você sabe como eu disse que
RewriteCond
se aplica a uma e apenas uma regra? Bem, você pode contornar isso encadeando.Como o primeiro RewriteRule possui o sinalizador Chain, a segunda regra de regravação será executada quando o primeiro, ou seja, quando a regra RewriteCond anterior for correspondida. Útil se as expressões regulares do Apache fizerem seu cérebro doer. No entanto, o método all-in-one-line que aponto na primeira seção é mais rápido do ponto de vista da otimização.
Isso pode ser simplificado através de sinalizadores:
Além disso, alguns sinalizadores também se aplicam ao RewriteCond. Notavelmente, NoCase.
Corresponderá a "ServerFault.com"
fonte
mod_rewrite
Primer muito bom e regex. +1.RewriteCond
processo é realmente processado após aRewriteRule
correspondência. Você pode dizer "mais sobre isso mais tarde" na parte superior, onde diz "RewriteCond anterior à RewriteRule torna essa regra sujeita à condicional". Você pode mencionar que as expressões regulares são expressões regulares compatíveis com Perl. Além disso, você tem um apóstrofo estranho em "... o RewriteRule considera que é o início das cordas ..."RewriteRule ^/blog/.*/(.*)$ /newblog/$1
não corresponde ao primeiro componente do diretório - por padrão, as regravações são gananciosas. /.*/(.*) corresponde a / 1 / (2) / e / 1/2/3/4/5 / (6) /, então você precisa de / [^ /] * / para corresponder apenas ao PRIMEIRO caminho componente.Vou adiar a excelente resposta de sysadmin1138 sobre esses pontos.
Além da ordem de sintaxe, da correspondência de sintaxe / expressões regulares e dos sinalizadores RewriteRule descritos por sysadmin1138, acredito que é importante mencionar que mod_rewrite expõe variáveis de ambiente do Apache com base nos cabeçalhos de solicitação HTTP e na configuração do Apache.
Eu recomendaria o Tutorial de depuração do mod_rewrite do AskApache para uma lista abrangente de variáveis que podem estar disponíveis para o mod_rewrite.
A maioria dos problemas com o RewriteRule resulta de um mal-entendido da sintaxe / falha do PCRE para escapar adequadamente de caracteres especiais ou da falta de percepção do conteúdo das variáveis usadas para correspondência.
Problemas típicos e solução recomendada:
IfModule
condicionais para evitar esse cenário), verifique a sintaxe da diretiva, comente as diretivas até que o problema seja identificadoPrimeiro, observe o conteúdo das variáveis de ambiente com as quais você planeja comparar - se você possui o PHP instalado, é tão simples quanto adicionar o seguinte bloco ao seu aplicativo:
... escreva suas regras (de preferência para teste em um servidor de desenvolvimento) e observe qualquer correspondência ou atividade inconsistente no seu arquivo Apache ErrorLog .
Para regras mais complexas, use a
RewriteLog
diretiva de mod_rewrite para registrar a atividade em um arquivo e definirRewriteLogLevel 3
AllowOverride all
afeta o desempenho do servidor, pois o Apache deve procurar.htaccess
arquivos e analisar diretivas a cada solicitação - se possível, mantenha todas as diretivas na configuração do VirtualHost para o seu site ou ative.htaccess
substituições apenas para os diretórios que precisam delas.As Diretrizes para webmasters do Google declaram explicitamente: "Não engane seus usuários nem apresente conteúdo diferente para os mecanismos de pesquisa que você exibe para os usuários, que geralmente é chamado de 'camuflagem'". - evite criar diretivas mod_rewrite que filtrem os robôs dos mecanismos de pesquisa.
Os robôs do mecanismo de pesquisa preferem um mapeamento de URI de conteúdo 1: 1 (esta é a base para classificar os links para o conteúdo) - se você estiver usando o mod_rewrite para criar redirecionamentos temporários ou se estiver exibindo o mesmo conteúdo em vários URIs, considere especificar um URI canônico dentro seus documentos HTML.
Este é um tópico enorme (e potencialmente controverso) por si só - melhor (IMHO) para abordar os usos caso a caso e permitir que os solicitantes determinem se as resoluções sugeridas são adequadas às suas necessidades.
Os truques e dicas do mod_rewrite do AskApache cobrem quase todos os casos de uso comuns que aparecem regularmente; no entanto, a solução "correta" para um determinado usuário pode depender da sofisticação da configuração do usuário e das diretivas existentes (é por isso que geralmente é um É uma boa idéia ver quais outras diretivas um usuário possui sempre que uma pergunta mod_rewrite surgir).
fonte
Redirect
ou, emRedirectMatch
vez disso. Veja também os documentos do Apache: Quando não usar mod_rewriteComo muitos administradores / desenvolvedores, venho lutando contra os meandros da reescrita de regras há anos e estou insatisfeito com a documentação existente do Apache, então decidi como um projeto pessoal descobrir como
mod_rewrite
realmente funciona e interage com o restante do Apache. nos últimos meses, tenho instrumentado casos de teste comstrace
+ drill no código-fonte para entender tudo isso.Aqui estão alguns comentários importantes que reescrevem os desenvolvedores de regras que devem ser considerados:
.htaccess
processamento PerDir ( ).Eu diria que, por causa disso, você quase precisa dividir as comunidades de usuários reescritos em duas categorias e tratá-las como completamente separadas:
Aqueles com acesso root à configuração do Apache . Normalmente, eles são admin / developer com um servidor / VM dedicado a aplicativos, e a mensagem aqui é bastante simples: evite usar
.htaccess
arquivos, se possível; faça tudo na sua configuração de servidor ou vhost. A depuração é bastante fácil, pois o desenvolvedor pode definir a depuração e ter acesso aos arquivos rewrite.log.Usuários de um serviço hospedado compartilhado (SHS) .
.htaccess
processamento / Perdir, pois não há alternativa disponível..htaccess
arquivo PerDir está selecionado e por quê. Ele não explica os meandros do ciclismo PerDir e como evitar isso.Existe possivelmente uma terceira comunidade: a administração e a equipe de suporte dos provedores de SHS que terminam com o pé nos dois campos e sofrem as consequências do exposto acima.
Escrevi algumas postagens no blog no estilo de artigo (por exemplo, mais sobre o uso de regras de reescrita em arquivos .htaccess ), que abordam muitos pontos detalhados que não repetirei aqui para manter esta postagem curta. Eu tenho meu próprio serviço compartilhado, além de apoiar alguns projetos dedicados e VM FLOSS. Comecei usando uma VM LAMP padrão como veículo de teste para minha conta SHS, mas no final achei melhor fazer uma VM espelhada adequada (descrita aqui ).
No entanto, em termos de como a comunidade de administradores deve dar suporte
.htaccess
aos usuários, sinto que precisamos desenvolver e oferecer:.htaccess
regras de reescritaDicas sobre como obter diagnósticos embutidos de suas regras (por exemplo,
[E=VAR:EXPR]
exploração do fato queEXPR
expandirá as referências anteriores ($ N ou% N) para torná-las disponíveis como diagnóstico para o script de destino.Se você ordenar topicamente suas regras de reescrita usando os sinalizadores [OR], [C], [SKIP] e [L] para que todo o esquema de reescrita funcione sem a necessidade de explorar o redirecionamento interno, você poderá adicionar o seguinte como regra 1 para evitar todos os problemas de loop:
fonte
.htaccess
tópicos e você verá. A maioria dos iniciantes fica irremediavelmente confusa - a maioria deles tem sua primeira experiência com um serviço LAMP e mod_rewrite em um serviço compartilhado e, portanto, não tem acesso root às configurações do sistema / vhost e precisa usar o processamento por diretório através de.htaccess
arquivos. Existem diferenças importantes que o iniciante precisa "sangrar". Eu me consideraria um usuário avançado e ainda estou descobrindo sutilezas. Como já disse, tive que usar a varredura de strace e de código-fonte para resolver alguns aspectos. Não deve ser necessário. :-(.htaccess
, o que é terrivelmente frágil, complicado e confuso, mesmo para especialistas. Eu ainda estou tendo problemas.Usando reescrever mapa
Há muitas coisas que você pode fazer com reescrever mapas. Os Rewritemaps são declarados usando a diretiva Rewritemap e podem ser usados nas avaliações RewritCond e nas Subscrições RewriteRule.
A sintaxe geral do RewriteMap é:
Por exemplo:
Você pode usar o nome do mapa para construções como esta:
O mapa contém pares de chave / valor. Se a chave for encontrada, o valor será substituído. Mapas simples são apenas arquivos de texto sem formatação, mas você pode usar mapas de hash e até consultas SQL. Mais detalhes estão nos documentos:
http://httpd.apache.org/docs/2.2/mod/mod_rewrite.html#rewritemap
Cordas sem escape.
Existem quatro mapas internos que você pode usar para fazer algumas manipulações. Especialmente seqüências de caracteres sem escape podem ser úteis.
Por exemplo: eu quero testar a string "café" na string de consulta. No entanto, o navegador escapará disso antes de enviá-lo para o meu servidor, portanto, eu preciso descobrir qual é a versão com escape de URL para cada string que eu desejo corresponder, ou posso simplesmente desescapá-la ...
Observe como eu uso um RewriteCond para capturar apenas o argumento do parâmetro de cadeia de consulta e, em seguida, use o mapa no segundo rewriteCond para removê-lo. Isso então é comparado. Observe também como eu preciso% 2 como chave no mapa de reescrita, pois% 1 conterá "location" ou "place". Quando você usa parênteses para agrupar padrões, eles também serão capturados, se você planeja usar o resultado da captura ou não ...
fonte
mod_rewrite
mecanismo regexp suporta grupos não capturadores como(?:location|place)
e isso terá apenas uma captura no exemplo.Uma armadilha muito fácil é quando você reescreve URLs que alteram o caminho aparente, por exemplo, de
/base/1234/index.html
para/base/script.php?id=1234
. Quaisquer imagens ou CSS com caminhos relativos ao local do script não serão encontrados pelo cliente. Várias opções para resolver isso podem ser encontradas neste FAQ .fonte
<base>
tag é mais fácil de seguir e ainda permite caminhos relativos.