8 Min. LesezeitTutorials

301-Redirect in .htaccess: Regeln, Reihenfolge, Query-Strings

Ein 301-Redirect in .htaccess ist eine Zeile mod_alias. Hier ist diese Zeile, wann RewriteRule stattdessen das richtige Werkzeug ist, und warum Reihenfolge wichtiger ist als Zeilenposition.

Marius Voß
DevRel · edge infra
Ein htaccess-301-Redirect als eine mod_alias-Zeile neben einer mod_rewrite-Regel, mit der Ausführungsreihenfolge zwischen beiden

Ein 301-Redirect in .htaccess ist eine Zeile:

Redirect 301 /old-page https://example.com/new-page

Das in der .htaccess-Datei in Ihrem Document Root speichern, und es ist sofort live. Apache liest die Datei bei jeder Anfrage, also gibt es keinen Neustart und kein Deploy. Die Direktive kommt von mod_alias, das auf praktisch jeder Apache-Installation vorhanden ist, und sie sendet ein 301 Moved Permanently mit einem Location-Header. Das ist die ganze Aufgabe.

Fast alles, was bei Apache-Redirects schiefgeht, passiert nach diesem Punkt: zu RewriteRule greifen, wo Redirect reichen würde, die beiden Module in einer Datei mischen und eine Reihenfolge bekommen, die niemand erwartet hat, oder den Query-String auf dem Weg verlieren. Dieser Beitrag behandelt die vier Regeln, die man sich merken sollte, die Ausführungsreihenfolge-Falle, die korrekt aussehende Dateien falsch funktionieren lässt, und wie man einen Redirect testet, ohne dass der Browser einen anlügt. Für das größere Bild, wo Redirects liegen können, siehe wie man eine URL weiterleitet.

Die eine Zeile, die die meisten Redirects abdeckt

Redirect nimmt einen Status, einen zu treffenden Pfad und ein Ziel entgegen. Das Ziel kann eine vollständige URL oder ein Pfad auf demselben Host sein:

Redirect 301 /old-page /new-page
Redirect 301 /shop https://shop.example.com/
RedirectMatch 301 ^/blog/([0-9]{4})/(.*)$ /articles/$2

Zwei Verhaltensweisen lohnt es sich zu kennen, bevor Sie es einsetzen. Erstens ist Apaches eigene Anleitung ausdrücklich der Meinung, dass dies das richtige Werkzeug ist: "Diese Art einfacher Weiterleitung einer URL, oder einer Klasse von URLs, an einen anderen Ort sollte mit diesen Direktiven erreicht werden statt mit RewriteRule."

Zweitens, und das überrascht Leute: "Denken Sie daran, dass Redirect Pfadinformationen erhält. Das heißt, ein Redirect für eine URL /one leitet auch alle URLs darunter weiter, wie /one/two.html und /one/three/four.html." Wenn Sie nur den exakten Pfad wollen, verankert RedirectMatch 301 ^/one$ ihn. Andernfalls haben Sie gerade einen ganzen Teilbaum weitergeleitet, was manchmal genau das ist, was Sie wollten, und manchmal ein sehr verwirrender Morgen.

RedirectMatch ist die Regex-Version, und sie deckt das meiste ab, wofür Leute mod_rewrite aufmachen. Erfasste Gruppen landen in $1, $2 und so weiter, sodass eine Verzeichnisumbenennung oder eine Änderung des datumsbasierten URL-Schemas ein Einzeiler ist.

Wann Sie wirklich RewriteRule brauchen

Zu mod_rewrite greifen, wenn die Entscheidung von etwas anderem als dem Pfad abhängt. Host, Query-String, Request-Methode, Cookies und User-Agent sind alle für RewriteCond sichtbar und für Redirect unsichtbar:

RewriteEngine On
RewriteCond %{QUERY_STRING} (^|&)ref=oldpartner(&|$)
RewriteRule ^landing$ /partners/oldpartner? [R=301,L]

Es gibt eine Falle im Per-Directory-Kontext, die für einen riesigen Anteil kopierter Regeln verantwortlich ist, die überhaupt nichts tun. Apache entfernt das Verzeichnispräfix vor dem Abgleich, sodass das Pattern nie einen führenden Schrägstrich sieht: "Das entfernte Präfix endet immer mit einem Schrägstrich, was bedeutet, dass der Abgleich gegen einen String erfolgt, der nie einen führenden Schrägstrich hat. Daher trifft ein Pattern mit ^/ im Per-Directory-Kontext nie zu."

Deshalb funktioniert RewriteRule ^/old$ /new [R=301], wenn jemand es in einen virtuellen Host einfügt, und scheitert lautlos in .htaccess. Den Schrägstrich weglassen: ^old$. Wenn Ihre Substitution ein relativer Pfad ist und das Rewrite in einem Unterverzeichnis liegt, brauchen Sie eventuell außerdem RewriteBase, um Apache zu sagen, worauf sich die Pfade relativ beziehen.

Die Ausführungsreihenfolge-Falle

Das ist die Falle, die Leute einen Nachmittag kostet. Die Zeilenposition in der Datei entscheidet nicht, welches Modul zuerst läuft.

Apache dokumentiert es unmissverständlich: "Wenn Sie Redirect und RewriteRule im selben Kontext mischen, beachten Sie, dass ihre Ausführungsreihenfolge davon abhängt, wo sie erscheinen. Im Server-/Virtual-Host-Kontext läuft mod_rewrite zuerst; im Per-Directory-Kontext (.htaccess) läuft mod_alias zuerst."

Das zweimal lesen, denn die Konsequenz ist gegen die Intuition. In einer .htaccess-Datei gewinnt ein Redirect am Ende der Datei gegen ein RewriteRule am Anfang. Verschieben Sie dieselben Regeln in einen virtuellen Host, dreht sich der Gewinner um. Auch das [L]-Flag rettet Sie nicht: Es bedeutet letzte Regel in diesem Durchlauf von mod_rewrite, nicht letzte Regel in der Datei, und es hat keine Autorität über ein anderes Modul.

Die praktische Regel, die ich befolge: ein Modul pro Datei. Braucht ein Projekt irgendwo Bedingungen, alle seine Redirects mit mod_rewrite umsetzen und die Redirect-Zeilen löschen. Gemischte Dateien sind der Ursprung der Bug-Reports, die lauten "der Redirect funktioniert auf Staging, aber nicht in Produktion", weil die beiden Umgebungen die Regeln in unterschiedliche Kontexte stellen.

Ausführungsreihenfolge von mod_alias und mod_rewrite zeigt, dass in einer htaccess-Datei mod_alias unabhängig von der Zeilenposition zuerst läuft

Query-Strings: erhalten, ersetzt oder gelöscht

Marketing-Links leben und sterben mit ihren Query-Strings, deshalb lohnt es sich, diese Tabelle anzupinnen. Alles davon ist dokumentiertes Verhalten und keine Folklore.

Was Sie schreibenUrsprünglicher Query-StringAnmerkungen
Redirect 301 /a /bWird übernommenmod_alias hängt ihn für Sie an
RedirectMatch 301 ^/a$ /bWird übernommenGleiches Modul, gleiches Verhalten
RewriteRule ^a$ /b [R=301]Läuft unverändert durchDas dokumentierte Standardverhalten
RewriteRule ^a$ /b?src=x [R=301]Durch Ihren ersetztIhre Parameter gewinnen
RewriteRule ^a$ /b?src=x [R=301,QSA]Mit Ihrem kombiniertQSA hängt den ursprünglichen an
RewriteRule ^a$ /b? [R=301]GelöschtEin einsames ? löscht ihn

Apaches Formulierung zum Standardverhalten: "Standardmäßig wird der Query-String unverändert durchgeleitet." Und zu den Flags: [QSA] "hängt jeden Query-String der ursprünglichen Anfrage-URL an jeden im Rewrite-Ziel erzeugten Query-String an", während [QSD] den eingehenden verwirft. Leiten Sie auf eine absolute URI weiter, kommt der Query-String mit, sofern Sie nicht [QSD] verlangen.

Der Fehler, den das verhindert, ist leise und teuer. Eine Regel, die den Query-String ersetzt, entfernt utm_source und utm_campaign auf dem Weg, Ihr Analytics-Tool schreibt die Sitzung direktem Traffic zu, und nichts meldet einen Fehler. Niemand merkt es, bis jemand fragt, warum die Frühjahrskampagne keine Gutschrift bekommen hat. UTM-Parameter fehlen in GA4 behandelt die Diagnose von der Analytics-Seite aus.

Wenn Sie sich dabei wiederfinden, Dutzende Kampagnen-Redirects in einer Server-Konfigurationsdatei zu pflegen, ist das ein Signal und keine lästige Pflicht. Server-Regeln brauchen ein Deploy, eine Apache-Config-Review und jemanden mit Shell-Zugriff. Kampagnen-Links auf Kurzlinks verschieben, die Sie selbst bearbeiten können und .htaccess für die strukturellen Redirects behalten, für die es gut ist.

HTTPS und www in einem Hop, nicht zwei

Das meistkopierte Snippet im Internet macht das in zwei Regelblöcken, was bedeutet, dass ein Besucher, der bei http://example.com/page ankommt, zweimal weitergeleitet wird: einmal, um TLS hinzuzufügen, einmal, um www hinzuzufügen. Zwei Hops, zwei Round-Trips, und jedes Mal ein etwas schwächeres Signal.

Eine Regel, zwei Bedingungen, ein Hop:

RewriteEngine On
RewriteCond %{HTTPS} !=on [OR]
RewriteCond %{HTTP_HOST} !^www\.example\.com$ [NC]
RewriteRule ^ https://www.example.com%{REQUEST_URI} [R=301,L]

Hinter einem CDN oder einem Load Balancer steht %{HTTPS} am Origin meist auf off, selbst wenn der Besucher HTTPS nutzt, weil TLS weiter vorne terminiert wurde. Stattdessen %{HTTP:X-Forwarded-Proto} prüfen:

RewriteCond %{HTTP:X-Forwarded-Proto} !https

Machen Sie das falsch, bauen Sie eine endlose Redirect-Schleife: Der Proxy sendet HTTPS, der Origin denkt, es sei HTTP, leitet auf HTTPS weiter, und so geht es rund, bis der Browser aufgibt. Wie man eine Redirect-Schleife behebt geht durch, wie man das aus den Antwort-Headern diagnostiziert.

Zwei separate htaccess-Regeln, die eine zweistufige Redirect-Kette erzeugen, verglichen mit einer einzigen Regel, die die kanonische HTTPS-www-URL in einem Hop erreicht

Warum es nicht funktioniert

In der Reihenfolge, in der ich sie prüfe:

  1. AllowOverride steht auf None. Apaches Dokumentation nennt das Standardverhalten: "Das bedeutet, .htaccess-Dateien werden komplett ignoriert, solange Sie sie nicht ausdrücklich für ein Verzeichnis aktivieren." Testen Sie das, indem Sie absichtlich Unsinn in die erste Zeile setzen. Kein 500-Fehler bedeutet, Ihre Datei wird überhaupt nicht gelesen, und jede Regel darin ist Dekoration.
  2. Die Datei liegt am falschen Ort oder ist falsch benannt. Sie muss .htaccess heißen, mit dem führenden Punkt, in dem Verzeichnis, auf das die Anfrage abbildet. Editoren, die hilfreich als htaccess.txt speichern, sind eine wiederkehrende Ursache.
  3. mod_rewrite ist nicht geladen. Redirect funktioniert, RewriteRule scheitert lautlos, was Leute eine Stunde lang ihre Regex anstarren lässt.
  4. Ihr Browser hat den alten 301 zwischengespeichert. Chrome und Firefox cachen permanente Redirects beide aggressiv, pro Browser-Profil, sodass der Fix, den Sie gerade deployt haben, für Sie unsichtbar bleibt und für alle anderen problemlos funktioniert. Während der Entwicklung R=302 verwenden und erst auf R=301 wechseln, sobald die Regel stimmt.
  5. Die Regel trifft ihr eigenes Ziel. RewriteRule ^(.*)$ /index.php/$1 ohne Absicherung ist der Klassiker. Eine Bedingung hinzufügen, die das Ziel ausnimmt.

Mit curl testen, nicht mit dem Browser

Ein Befehl verrät Ihnen den Status, das Ziel und wie viele Hops es gebraucht hat:

curl -sIL https://example.com/old-page | grep -iE '^HTTP|^location'

Die Ausgabe als Sequenz lesen. Zwei HTTP/2 301-Zeilen vor dem 200 bedeuten zwei Hops, und jeder Hop ist ein echter Round-Trip für einen echten Besucher in einem Mobilfunknetz. Googles Dokumentation zu Redirects behandelt einen permanenten Redirect als das stärkste Signal zum Konsolidieren einer URL, und in einem Schritt dorthin zu kommen ist strikt besser, als in drei Schritten dorthin zu kommen. Unser Link-Checker zeigt dieselbe Kette in einem Browser, und 301 vs. 302 Redirects behandelt, welchen Status man senden sollte, wenn man unsicher ist.

Die Pfade testen, die wichtig sind, statt nur den, den Sie gerade geschrieben haben: die Wurzel, einen tiefen Pfad, einen Pfad mit Query-String und das Ziel selbst. Letzteres fängt Schleifen ab, bevor Ihre Besucher es tun.

Wann man .htaccess überhaupt nicht verwenden sollte

Apaches eigene Position ist eindeutig. "Wenn Sie Zugriff auf die Hauptserver-Konfigurationsdatei haben, sollten Sie Ihre gesamte Konfiguration dort ablegen statt in .htaccess-Dateien," weil das Parsen bei jeder Anfrage echte Arbeit kostet: "Das Zulassen von .htaccess-Dateien verursacht einen Performance-Verlust, egal ob Sie sie tatsächlich nutzen." Bei Shared Hosting haben Sie keine Wahl. Auf einem Server, den Sie kontrollieren, ist die Hauptkonfiguration die bessere Heimat für alles Strukturelle.

Es gibt einen zweiten Grund, Regeln komplett aus der Datei herauszuhalten, und der hat nichts mit Performance zu tun. Redirects, die im Druck, in einem QR-Code oder in der Präsentation von jemand anderem auftauchen, müssen Ihren Webserver, Ihre CMS-Migration und möglicherweise Ihren Hosting-Anbieter überleben. Eine Regel in .htaccess ist ein unachtsames Deploy davon entfernt zu verschwinden, und niemand meldet einen toten gedruckten Link, bis die Kampagne vorbei ist. Strukturelle Redirects gehören in den Server; Kampagnen- und Druck-Links gehören an einen Ort, den Sie in Sekunden bearbeiten und ohne das Grepen von Access-Logs messen können.

Die Cornerstone-Serie lesen

Dieser Beitrag gehört zum Tutorials-Cluster. Für die vollständige Übersicht behandelt Arten von Redirects jeden Statuscode und jede clientseitige Methode, und wie man eine URL weiterleitet behandelt die sechs Orte, an denen ein Redirect liegen kann.

Verwandte Beiträge im Blog

Häufig gestellte Fragen

Wie erstelle ich einen 301-Redirect in .htaccess?

Eine Zeile in die .htaccess-Datei in Ihrem Document Root einfügen: Redirect 301 /old-page https://example.com/new-page. Apache liest .htaccess bei jeder Anfrage, der Redirect ist also live, sobald Sie die Datei speichern. Kein Neustart, kein Deploy. Diese Direktive kommt von mod_alias, das auf praktisch jeder Apache-Installation aktiviert ist.

Was ist der Unterschied zwischen Redirect und RewriteRule?

Redirect und RedirectMatch kommen von mod_alias und tun eine Sache: einen Statuscode und einen Location-Header senden. RewriteRule kommt von mod_rewrite und kann den Host, den Query-String, Cookies oder den User-Agent prüfen, bevor es entscheidet. Apaches eigene Dokumentation sagt, einfache Weiterleitungen sollten mod_alias statt RewriteRule verwenden, und behandelt mod_rewrite als letztes Mittel.

Warum funktioniert mein .htaccess-Redirect nicht?

Fünf Ursachen decken fast alles ab: AllowOverride steht auf None, sodass die Datei komplett ignoriert wird, die Datei liegt nicht im Document Root oder ist falsch benannt, mod_rewrite ist nicht geladen, Ihr Browser hat einen früheren 301 zwischengespeichert und fragt den Server nie wieder, oder die Regel trifft ihr eigenes Ziel und läuft in einer Schleife. Mit curl testen statt mit dem Browser, denn ein zwischengespeicherter 301 lässt eine korrigierte Regel kaputt wirken.

Überlebt der Query-String einen 301-Redirect in .htaccess?

Bei Redirect und RedirectMatch ja, er wird automatisch übernommen. Bei RewriteRule hängt die Antwort von der Substitution ab: kein Fragezeichen darin, und der ursprüngliche Query-String läuft durch, ein Fragezeichen mit eigenen Parametern ersetzt ihn, ein einsames Fragezeichen am Ende löscht ihn, und das QSA-Flag kombiniert beide. Macht man das falsch, verschwinden UTM-Parameter stillschweigend.

Wie leite ich HTTP zu HTTPS und Non-www zu www in einem Hop weiter?

Eine Regel mit zwei durch OR verbundenen Bedingungen verwenden, die in einem einzigen Schritt auf das kanonische Schema und den kanonischen Host umschreibt. Zwei getrennte Regelblöcke erzeugen zwei Redirects für jeden, der auf http:// ohne www ankommt, und jeder zusätzliche Hop kostet Latenz und verwässert das Signal. Hinter einem Proxy oder CDN %{HTTP:X-Forwarded-Proto} statt %{HTTPS} prüfen, sonst bauen Sie eine Schleife.

Verlangsamt .htaccess eine Website?

Leicht, und unausweichlich. Apaches Dokumentation ist da unmissverständlich: Das Zulassen von .htaccess-Dateien verursacht einen Performance-Verlust, egal ob Sie sie nutzen, weil httpd bei jeder Anfrage in jedem Verzeichnis nach der Datei sucht. Haben Sie Zugriff auf die Hauptserver-Konfiguration, gehören dieselben Regeln stattdessen dorthin, einmal beim Start geladen.

Elido testen

URL einfügen, kurzer Link in Sekunden

Kein Konto nötig. Link bleibt 30 Tage aktiv. Konto erstellen, um ihn dauerhaft zu behalten.

Kostenlos, keine Anmeldung erforderlich · 2 pro Tag

Elido testen

URL-Shortener mit EU-Hosting: eigene Domains, tiefe Analytik und eine offene API. Kostenloser Tarif - keine Kreditkarte nötig.

Tags
htaccess 301 redirect
apache redirect
mod_rewrite
301 redirect
redirect https
url redirect

Weiterlesen