Reescrita leva ao loop infinito de redirecionamento 301 em diretórios existentes

3

Eu passei por perguntas / soluções encontradas aqui, tentei várias abordagens (incluindo a diretiva [L]), mas nada realmente funcionou.

Visão geral da situação

Debian rodando o Apache 2.2 fazendo proxy através do nginx

Objetivo

Redirecione tudo para /index.php e garanta sempre uma barra final.

Exclua os seguintes diretórios da regra:

  • js_static
  • media

Exclua todos os arquivos .css da regra.

O problema

O Apache / nginx leva a um loop de redirecionamento 301 quando eu chamo www.url.com/js_static . (Problema ocorre também com barra final - não faz diferença)

Abordagem da solução atual

O nginx é configurado assim:

gzip_proxied any;
rewrite ^/(.*)/$ /$1;
ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:AES256+EECDH:AES256+EDH';

O Apache é configurado desta maneira:

RewriteEngine On
RewriteCond %{SCRIPT_FILENAME} !^.+\.(css)
RewriteCond %{REQUEST_URI} !^.+js_static
RewriteCond %{REQUEST_URI} !^.+media
RewriteRule ^(.*)$ /index.php/$1
AllowEncodedSlashes On

Não consigo ver onde está o problema. Uma teoria que eu tinha era que a combinação de nginx / apache reescreveva o problema, então eu mexi na configuração, mas não adiantou, infelizmente.

Alguém pode identificar o problema aqui?

    
por Cummander Checkov 03.12.2016 / 02:21

1 resposta

0

tl; dr "O problema" provavelmente é causado pelo mod_dir (Apache) anexando automaticamente a barra ao solicitar um diretório físico. No entanto, desabilitar mod_dir (ou seja, DirectorySlash Off ) não é necessariamente a resposta.

Problem occurs also with trailing slash – makes no difference

Em sua configuração Nginx (seu proxy frontend), você está incondicionalmente tirando a barra final de todas as URLs (incluindo diretórios) através de uma reescrita interna. Então, se você incluir a barra no final do pedido inicial, de fato não fará diferença.

O Apache mod_dir (por padrão) anexará automaticamente uma barra ao solicitar um diretório físico (que ainda não possui uma barra final) por meio de um redirecionamento 301 externo. Ele faz isso para "consertar" o URL. "Um diretório" não é estritamente um recurso válido (o que você espera que seja retornado?). Uma vez "consertado", mod_dir então tenta retornar o documento de índice de diretório (por exemplo, index.html ) nesse diretório:

  1. example.com/directory 301 redirecionar para example.com/directory/
  2. example.com/directory/ reescrita interna para example.com/directory/index.html (ou qualquer que seja o DirectoryIndex document encontrado). Ou um 403 Proibido se não houver nenhum índice de diretório (a menos que os índices de diretório automático estejam ativados - não é recomendado).

No entanto, após o redirecionamento para example.com/directory/ , a solicitação atinge seu proxy Nginx novamente, o que retira a barra à direita .... etc. etc. 301 loop de redirecionamento.

Minha preferência pessoal é sempre deixar a barra final nos diretórios físicos. No entanto, se você quiser remover a barra final de todas as URLs, será necessário desativar o comportamento automático de mod_dir e anexar manualmente a barra final por meio de uma reconfiguração interna (porque solicitar um diretório sem barra não é estritamente válido nesta instância ).

Tente alterar sua configuração do Apache para o seguinte

AllowEncodedSlashes On
DirectorySlash Off

RewriteEngine On

# Internally rewrite any directories that do not have a trailing slash
RewriteCond %{REQUEST_FILENAME} -d
RewriteCond %{REQUEST_URI} (.*)
RewriteRule !/$ %1/ [L]

# Internally rewrite all non-static resources to index.php (with path info)
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^/(.*)$ /index.php/$1 [L]

Eu assumo que isso está na configuração do seu servidor (e não no .htaccess)? No entanto, seu RewriteRule anterior teria resultado em uma barra dupla na substituição quando usado na configuração do servidor. Isso ainda deve ter sido resolvido corretamente, mas pode quebrar algumas coisas.

Eu também fiz isso mais "genérico". Em vez de verificar especificamente os arquivos .css e os URLs que contêm js_static ou media , basta verificar se a solicitação não é para um arquivo físico. Isso é muito mais comum (e flexível) como um "controlador de frente". No entanto, você pode alterar isso de volta se precisar especificamente (mas há problemas em potencial se você o fizer).

...redirect loop when I call www.example.com/js_static

Além de: eu não esperaria que isso fosse uma solicitação válida de qualquer maneira?

Apenas para refletir as preocupações da TeroKilkanen nos comentários. Não é recomendado usar o Nginx e o Apache para reescrever arquivos relacionados.

    
por 05.12.2016 / 11:54