Warum bekomme ich einen doppelten Schrägstrich, je nachdem, wo sich meine RewriteRule befindet?

9

Ich verwende den folgenden Code, um alle WWW-Anfragen an Nicht-WWW-URLs weiterzuleiten:

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

Dies funktioniert hervorragend in einer .htaccess-Datei im Stammverzeichnis meiner Website.
Zum Beispiel
www.example.com -> example.com/
www.example.com/ -> example.com/
www.example.com/other_page -> example.com/other_page

Wenn ich jedoch denselben Code in meine VirtualHost-Konfiguration verschiebe, enthalten die neu geschriebenen URLs einen doppelten Schrägstrich.
www.example.com -> example.com//
www.example.com/ -> example.com//
www.example.com/other_page -> example.com//other_page

Ich habe es behoben, indem ich den Schrägstrich aus der Umschreiberegel entfernt habe:

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

Aber ich kann den Grund dafür nicht verstehen. Weiß jemand warum?

Davekaro
quelle

Antworten:

10

So wie ich es verstehe, ist in .htaccess-Dateien die Zeichenfolge, die mod_rewrite in Ihrer Regel verarbeitet, relativ zu dem Verzeichnis, in dem sich die .htaccess-Datei befindet, sodass sie am Anfang kein / hat.

Im VirtualHost-Eintrag ist die von ihm verarbeitete Zeichenfolge absolut im Stammverzeichnis des Servers und enthält daher das /.

Dies führt zu subtilen Unterschieden in der Funktionsweise von mod_rewrite.

Hier ist jemand mit einem ähnlichen Problem und einer ähnlichen Lösung:

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

Dies sollte in beiden Fällen funktionieren, vorausgesetzt, ich erinnere mich an meine Flucht:

RewriteEngine On
RewriteCond %{HTTP_HOST} ^www\.example\.org$ [NC]
RewriteRule ^\/?(.*?)$ http://example.com/$1 [R=301,L]
Neobyte
quelle
Vielen Dank! Jetzt verstehe ich zumindest warum. Ist dies jedoch aus irgendeinem Grund besser, als nur das / vor dem $ 1 zu entfernen, wie ich es in meiner ursprünglichen Frage gezeigt habe?
Davekaro
1
Nicht besser oder schlechter, es ist nur ein Block, den Sie zwischen .htaccess von VirtualHost wechseln können, ohne ihn jedes Mal bearbeiten zu müssen, um Kontextunterschiede zu behandeln. Wenn dein Weg für dich funktioniert, bleib dabei! :)
Neobyte
Oh, das stimmt - Ihre Methode funktioniert sowohl in .htaccess als auch in VirtualHost. Das macht es besser IMO :)
Davekaro
4
Ich hatte genau das gleiche Problem wie @davekaro und habe Ihre Lösung ausprobiert. Die letzte Zeile hat bei mir nicht funktioniert. RewriteRule ^/?(.*)$ http://example.com/$1 [R=301,L]hat den Trick gemacht.
Kenny Rasschaert
2

Dies geschieht, weil Sie einen ersten Schrägstrich mit erfassen (.*)und dann an der neuen Position einen weiteren Schrägstrich davor anwenden /$1. Dies war zuvor nicht der Fall, da sich mod_rewrite beim Betrieb in einem Verzeichniskontext etwas anders verhält als in einem Serverkontext.

Sie können dies vermeiden, indem Sie den Schrägstrich optional vorwegnehmen. Darüber hinaus können Sie RedirectMatch in einem leeren VirtualHost mit Ihren überschüssigen Domänen verwenden, wodurch etwas weniger Verarbeitung entsteht und sauberer aussehen kann.

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

Dan Carley
quelle
Nett. Ich mag den RedirectMatch-Ansatz. Ich werde wahrscheinlich damit weitermachen, da es wirklich eine Weiterleitung ist, die ich erreichen möchte.
Davekaro
1

Der Vollständigkeit halber füge ich diesen Beitrag hinzu.

In der Apache-Dokumentation wird erklärt, warum dieses Verhalten sehr gut auftritt und warum die Direktive 'RewriteBase' vorhanden ist.

Durch einfaches Einfügen der Anweisung 'RewriteBase' in Ihre .htaccess-Datei sollte das gewünschte Ergebnis erzielt werden.

Beispiel:

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

Aus der Apache 2.2 mod_rewrite-Dokumentation:

Die RewriteBase-Direktive legt explizit die Basis-URL für das Umschreiben pro Verzeichnis fest.

Meine Faustregel lautet, fast immer 'RewriteBase' in .htaccess-Dateien zu verwenden und nicht in der Apache-Konfiguration.


quelle
0

Ich hatte keine Zeit, dieses Problem zu lösen, also schreibe einfach // nach / :)

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