Por que recebo uma barra dupla à direita, dependendo da localização da minha RewriteRule?

9

Estou usando o código a seguir para direcionar todas as solicitações de www para URLs não www:

RewriteEngine On
RewriteCond %{HTTP_HOST} ^www\.example\.org$ [NC]
RewriteRule ^(.*)$ http://example.com/$1 [R=301,L]

Isso funciona muito bem dentro de um arquivo .htaccess na raiz do meu site.
Por exemplo,
www.example.com -> example.com/
www.example.com/ -> example.com/
www.example.com/other_page -> exemplo.com/other_page

No entanto, se eu mover esse mesmo código para minha configuração do VirtualHost, os URLs reescritos conterão uma barra dupla à direita.
www.example.com -> example.com//
www.example.com/ -> example.com//
www.example.com/other_page -> example.com//other_page

Corrigi-o removendo a barra da regra de reescrita:

RewriteEngine On
RewriteCond %{HTTP_HOST} ^www\.example\.org$ [NC]
RewriteRule ^(.*)$ http://example.com$1 [R=301,L]

Mas não consigo entender o motivo disso. Alguém sabe o porquê?

davekaro
fonte

Respostas:

10

Pelo que entendi, nos arquivos .htaccess, a string que mod_rewrite processa na sua regra é relativa ao diretório em que o arquivo .htaccess está, portanto, não terá um / no início.

Na entrada VirtualHost, a cadeia de caracteres processada é absoluta para a raiz do servidor e, portanto, inclui o /.

Faz diferenças sutis em como o mod_rewrite funciona.

Aqui está alguém com um problema semelhante e solução:

http://forum.modrewrite.com/viewtopic.php?p=56322&sid=77f72967f59200b5b5de174440234c3a

Isso deve funcionar nos dois casos, supondo que eu lembrei de ter escapado corretamente:

RewriteEngine On
RewriteCond %{HTTP_HOST} ^www\.example\.org$ [NC]
RewriteRule ^\/?(.*?)$ http://example.com/$1 [R=301,L]
Neobyte
fonte
Obrigado! Agora eu entendo o porquê, pelo menos. No entanto, isso é melhor por algum motivo do que apenas remover o / antes do $ 1, como mostro na minha pergunta original?
Davekaro
1
Não é melhor ou pior, é apenas um bloco que você pode alternar entre .htaccess do VirtualHost sem precisar editá-lo toda vez para lidar com diferenças de contexto. Se o seu caminho funciona para você, fique com ele! :)
Neobyte
Ah, está certo - seu método funcionará no .htaccess e no VirtualHost. Que o torna melhor IMO :)
davekaro
4
Eu tive exatamente o mesmo problema que o @davekaro e tentei sua solução. A última linha não funcionou para mim. RewriteRule ^/?(.*)$ http://example.com/$1 [R=301,L]fez o truque.
Kenny Rasschaert
2

Isso está acontecendo porque você está capturando uma barra inicial (.*)e aplicando outra barra antes dela no novo local /$1. Isso não aconteceu antes porque o mod_rewrite se comporta de maneira um pouco diferente ao operar em um contexto por diretório, em oposição a um contexto por servidor.

Você pode evitar isso opcionalmente antecipando a barra. Além disso, você pode usar o RedirectMatch em um VirtualHost vazio com seus domínios excedentes, o que cria um pouco menos de processamento e pode parecer mais limpo.

<VirtualHost *>
ServerName example.com
ServerAlias other.example.com
..
RedirectMatch permanent ^/?(.*) http://example.com/$1
</VirtualHost>

Dan Carley
fonte
Agradável. Eu gosto da abordagem RedirectMatch. Provavelmente irei com isso, já que realmente é um redirecionamento que desejo realizar.
Davekaro
1

Estou incluindo este post por completo.

A documentação do Apache explica por que esse comportamento ocorre muito bem e é o motivo da existência da diretiva 'RewriteBase'.

Basta incluir a diretiva 'RewriteBase' em seu arquivo .htaccess para obter o resultado desejado.

Exemplo:

RewriteEngine On
RewriteBase /
RewriteCond %{HTTP_HOST} ^www\.example\.org$ [NC]
RewriteRule ^(.*)$ http://example.com/$1 [R=301,L]

Na documentação mod_rewrite do Apache 2.2:

A diretiva RewriteBase define explicitamente o URL base para reescrições por diretório.

Minha regra geral é quase sempre usar 'RewriteBase' em arquivos .htaccess, e não usá-lo na configuração do Apache.


fonte
0

Como não tive tempo de resolver esse problema, basta reescrever // para / :)

RewriteCond %{THE_REQUEST} //
RewriteRule ^(.*)$ http://domain.com [R=301,L]
user956584
fonte