mod_rewrite: reescreve o arquivo existente para slug, slug para o arquivo existente

1

Minha situação é a seguinte: Eu tenho arquivos estáticos na pasta public/ no meu servidor local. Qualquer pedido que entrar deve ser encaminhado para essa pasta, mas se um arquivo nessa pasta for acessado diretamente, ele deve ser um 404 ou redirecionar para o 'slug'. Exemplo:

Request: /my-file
Should rewrite to: /public/my-file.html
URL should be: http://localhost/my-file

Request: /public/my-file.html
Should rewrite to: /public/my-file.html
URL should be: http://localhost/my-file

Eu tenho as seguintes regras e condições no meu .htaccess :

RewriteCond %{DOCUMENT_ROOT}/public/%{REQUEST_URI}.html -f
RewriteRule ^.*$ /public/$0.html [L,C]
RewriteCond %{REQUEST_URI} ^/public
RewriteRule ^public/(.+).html$ /$1 [R=301,L]

De cima para baixo:

  1. O /public/{request}.html é um arquivo?
  2. Reescreva se (1) for verdadeiro: /public/{request}.html e encadeie para (3) para evitar um loop de redirecionamento
  3. A solicitação original começa com /public ?
  4. Reescreva se (3) for verdadeiro e a solicitação original corresponder a public/{request}.html : /{request} . Também crie um 301 header, que informa ao meu navegador e rastreadores que a página foi movida permanentemente. A solicitação será executada em todas as regras novamente

Então, se fizermos esses dois pedidos:

1. Request: /my-file
  1. /public/my-file.html é avaliado como verdadeiro; o arquivo existe na minha pasta.
  2. Reescreve para: /public/my-file.html , cadeia para 3
  3. A solicitação original não corresponde.
  4. Ignorado

Até agora, tudo bem; o arquivo correto é mostrado com o URL que eu quero. Solicitação número 2, que é uma solicitação para o arquivo real, como existe na estrutura do arquivo:

2. Request: /public/my-file.html
  1. public/public/my-file.html.html avalia como false, o arquivo não existe na minha pasta.
  2. Ignorado
  3. A solicitação original corresponde: começa com /public
  4. Reescreva public/my-file.html para /my-file e vá para o início.

Agora, depois de (4) no segundo exemplo, eu diria que a solicitação corresponde ao primeiro exemplo, o que significa que eu recebo a página que estou procurando com o URL correto (por causa do 301). Mas não funciona: o URL não muda, estou recebendo a página que estou procurando, mas não o URL (que deve ser /my-file ).

Alguém tem ponteiros? Eu acho que estou quase lá, mas fazendo algo errado com o encadeamento ou redirecionamento. Obrigado!

Editar

Depois de ter tentado todos os tipos de coisas, finalmente decidi que o que eu quero provavelmente não é possível. Eu quero redirecionar um arquivo existente ( public/my-file.html ) para um arquivo inexistente ( my-file ) visualmente , mas internamente eu quero que ele solicite o caminho do arquivo existente. Isso invariavelmente resultará em um loop de redirecionamento, porque mod_rewrite simplesmente não funciona dessa maneira:

User typed: website.com/my-file
Rewrites to file path: .../wwwroot/public/my-file.html
Internal redirect
Rewriterule found: /public/my-file.html should redirect to my-file
See above.

Eu não encontrei nenhuma situação comparável aqui no ServerFault ou no StackOverflow - geralmente a regravação vai para um arquivo .php genérico, não para um arquivo .html existente.

Eu marquei a resposta de Krist van Besien como a certa, uma vez que me apontou na direção certa para descobrir tudo isso.

Editar 2

Em uma pergunta de acompanhamento, o problema foi resolvido usando %{THE_REQUEST} : Veja aqui

    
por Community 31.03.2013 / 19:45

2 respostas

1

O fato de não funcionar como esperado tem a ver com a ordem em que RewriteConds e RewriteRules são executados. RewriteRules são avaliados antes dos RewriteConds que os precedem. Portanto, o pedido que seu pedido de /public/my-file.html é processado é assim: (Vou manter sua numeração)

  • Primeiro, a URL é checada com o padrão de teste de 2. E isso corresponde. .* corresponde a qualquer coisa depois de tudo ..
  • Em seguida, o RewriteCond 1 é avaliado. Como isso falha, a subsituição em 2 não é executada.
  • O URI é verificado em relação ao padrão de teste de 4. Esse padrão de teste não corresponde, pois seu URI é iniciado com /. A regra falha, então o RewriteCond em 3 nunca é avaliado.

RewriteConds (e você pode ter vários) pertencem ao RewriteRule que os segue e só são avaliados se o padrão no RewriteCond for o primeiro. Isso é um pouco contra-intuitivo, eu sei.

Leia sobre a sintaxe aqui: Redirecionar, Alterar URLs ou Redirecionar HTTP para HTTPS no Apache - Tudo o que você sempre quis saber sobre as regras do Mod_Rewrite, mas tinha medo de perguntar

Como resolver seu problema?

Talvez algo como:

RewriteRule  ^/public/(.*)$     /$1 [R=301,L]
RewriteRule  ^(-*)$             /public/$1

E uma última dica: ative o registro de regravação. Você vai aprender um pacote ...

    
por 01.04.2013 / 11:17
0

Você pode verificar arquivos / pastas reais e pular ...

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d

Você pode ter várias Cond's antes da regra.

    
por 31.03.2013 / 22:51