Een 301-redirect in .htaccess is één regel:
Redirect 301 /old-page https://example.com/new-page
Bewaar dat in het .htaccess-bestand in je document root en het is meteen live. Apache leest het bestand bij elk verzoek, dus er is geen restart en geen deploy. De directive komt van mod_alias, dat op vrijwel elke Apache-installatie aanwezig is, en het verstuurt een 301 Moved Permanently met een Location-header. Dat is de hele klus.
Bijna alles wat er misgaat met Apache-redirects, gebeurt na dit punt: naar RewriteRule grijpen terwijl Redirect had volstaan, de twee modules in één bestand mengen en een volgorde krijgen die niemand verwachtte, of de querystring onderweg verliezen. Dit artikel behandelt de vier regels die het waard zijn om te onthouden, de valkuil rond de uitvoeringsvolgorde die correct uitziende bestanden zich laat misdragen, en hoe je een redirect test zonder dat je browser tegen je liegt. Voor het bredere beeld van waar redirects kunnen zitten, zie een URL redirecten.
De ene regel die de meeste redirects dekt
Redirect neemt een status, een pad om te matchen, en een doel. Het doel kan een volledige URL zijn of een pad op dezelfde host:
Redirect 301 /old-page /new-page
Redirect 301 /shop https://shop.example.com/
RedirectMatch 301 ^/blog/([0-9]{4})/(.*)$ /articles/$2
Twee gedragingen zijn het weten waard voordat je het gebruikt. Ten eerste is Apache's eigen richtlijn expliciet dat dit het juiste gereedschap is: "Dit soort eenvoudige omleiding van één URL, of een klasse van URL's, naar iets anders, moet worden bereikt met deze directives in plaats van met RewriteRule."
Ten tweede, en dit verrast mensen: "Onthoud dat Redirect padinformatie behoudt. Dat wil zeggen, een redirect voor een URL /one redirect ook alle URL's daaronder, zoals /one/two.html en /one/three/four.html." Wil je alleen het exacte pad, dan verankert RedirectMatch 301 ^/one$ dat. Anders heb je zojuist een hele subboom geredirect, wat soms precies is wat je wilde en soms een heel verwarrende ochtend.
RedirectMatch is de regex-versie, en die dekt het meeste waarvoor mensen mod_rewrite openen. Gevangen groepen landen in $1, $2, enzovoort, waardoor het hernoemen van een directory of het wijzigen van een datumgebaseerd URL-schema een one-liner is.
Wanneer je RewriteRule echt nodig hebt
Grijp naar mod_rewrite wanneer de beslissing afhangt van iets anders dan het pad. Host, querystring, requestmethode, cookies en user agent zijn allemaal zichtbaar voor RewriteCond en onzichtbaar voor Redirect:
RewriteEngine On
RewriteCond %{QUERY_STRING} (^|&)ref=oldpartner(&|$)
RewriteRule ^landing$ /partners/oldpartner? [R=301,L]
Er is één addertje onder het gras in per-directory-context dat een groot deel verklaart van gekopieerd-en-geplakte regels die helemaal niets doen. Apache strip het directoryvoorvoegsel vóór het matchen, dus het patroon ziet nooit een leidende slash: "Het verwijderde voorvoegsel eindigt altijd met een slash, wat betekent dat het matchen gebeurt tegen een string die nooit een leidende slash heeft. Daarom matcht een Pattern met ^/ nooit in per-directory-context."
Daarom werkt RewriteRule ^/old$ /new [R=301] wanneer iemand het in een virtual host plakt, en faalt het stilletjes in .htaccess. Laat de slash weg: ^old$. Wanneer je vervanging een relatief pad is en de rewrite in een subdirectory staat, heb je mogelijk ook RewriteBase nodig om Apache te vertellen waar de paden relatief aan zijn.
De valkuil van de uitvoeringsvolgorde
Dit is degene die mensen een middag kost. De positie van de regel in het bestand bepaalt niet welke module eerst draait.
Apache documenteert het glashelder: "Als je Redirect en RewriteRule toch in dezelfde context mengt, houd er dan rekening mee dat hun uitvoeringsvolgorde afhangt van waar ze verschijnen. In server/virtual-host-context draait mod_rewrite eerst; in per-directory-context (.htaccess) draait mod_alias eerst."
Lees dat twee keer, want het gevolg is contra-intuïtief. In een .htaccess-bestand wint een Redirect onderaan het bestand het van een RewriteRule boven aan. Verplaats dezelfde regels naar een virtual host en de winnaar draait om. De [L]-vlag redt je ook niet: die betekent laatste regel in deze pass van mod_rewrite, niet laatste regel in het bestand, en heeft geen zeggenschap over een andere module.
De praktische regel die ik volg: één module per bestand. Als een project ergens condities nodig heeft, doe dan al zijn redirects met mod_rewrite en verwijder de Redirect-regels. Gemengde bestanden zijn waar de bugreports vandaan komen die luiden "de redirect werkt op staging maar niet op productie", omdat de twee omgevingen de regels in verschillende contexten plaatsen.
Querystrings: behouden, vervangen of gewist
Marketinglinks leven en sterven met hun querystrings, dus deze tabel is het waard om op te hangen. Het is allemaal gedocumenteerd gedrag in plaats van folklore.
| Wat je schrijft | Oorspronkelijke querystring | Opmerkingen |
|---|---|---|
Redirect 301 /a /b | Meegenomen | mod_alias voegt hem voor je toe |
RedirectMatch 301 ^/a$ /b | Meegenomen | Zelfde module, zelfde gedrag |
RewriteRule ^a$ /b [R=301] | Ongewijzigd doorgegeven | De gedocumenteerde standaard |
RewriteRule ^a$ /b?src=x [R=301] | Vervangen door de jouwe | Jouw parameters winnen |
RewriteRule ^a$ /b?src=x [R=301,QSA] | Gecombineerd met de jouwe | QSA voegt de oorspronkelijke toe |
RewriteRule ^a$ /b? [R=301] | Gewist | Een kaal ? wist hem |
Apache's formulering over de standaard: "Standaard wordt de querystring ongewijzigd doorgegeven." En over de vlaggen: [QSA] "voegt elke querystring van de oorspronkelijke request-URL toe aan elke querystring die in het rewrite-doel wordt aangemaakt", terwijl [QSD] de binnenkomende weggooit. Als je redirect naar een absolute URI, komt de querystring mee, tenzij je [QSD] opgeeft.
De fout die dit voorkomt, is stil en duur. Een regel die de querystring vervangt, strip utm_source en utm_campaign onderweg, je analytics wijst de sessie toe aan direct verkeer, en niets geeft een foutmelding. Niemand merkt het totdat iemand vraagt waarom de lentecampagne geen krediet kreeg. UTM-parameters niet zichtbaar in GA4 behandelt de diagnose vanaf de analyticskant.
Als je merkt dat je tientallen campagneredirects in een serverconfigbestand onderhoudt, is dat een signaal, geen klusje. Serverregels vereisen een deploy, een Apache-configreview, en iemand met shell-toegang. Zet campagnelinks op korte links die je zelf kunt bewerken en houd .htaccess voor de structurele redirects waar het goed in is.
HTTPS en www in één sprong, niet twee
Het meest gekopieerde snippet op het internet doet dit in twee regelblokken, wat betekent dat een bezoeker die aankomt op http://example.com/page twee keer wordt geredirect: eenmaal om TLS toe te voegen, eenmaal om www toe te voegen. Twee sprongen, twee round trips, en bij elke een iets zwakker signaal.
Eén regel, twee voorwaarden, één sprong:
RewriteEngine On
RewriteCond %{HTTPS} !=on [OR]
RewriteCond %{HTTP_HOST} !^www\.example\.com$ [NC]
RewriteRule ^ https://www.example.com%{REQUEST_URI} [R=301,L]
Achter een CDN of een load balancer staat %{HTTPS} bij de origin meestal op off, ook wanneer de bezoeker op HTTPS zit, omdat TLS upstream is getermineerd. Test in plaats daarvan %{HTTP:X-Forwarded-Proto}:
RewriteCond %{HTTP:X-Forwarded-Proto} !https
Doe je dit fout, dan bouw je een oneindige redirect-lus: de proxy stuurt HTTPS, de origin denkt dat het HTTP is, redirect naar HTTPS, en zo gaat het rond totdat de browser het opgeeft. Een redirect-lus oplossen behandelt het diagnosticeren daarvan vanuit de responseheaders.
Waarom het niet werkt
In de volgorde waarin ik ze controleer:
AllowOverridestaat opNone. Apache's documentatie beschrijft de standaard: "Dit betekent dat.htaccess-bestanden volledig worden genegeerd, tenzij je ze expliciet inschakelt voor een directory." Test dit door bewust rommel op de eerste regel te zetten. Geen 500-fout betekent dat je bestand helemaal niet wordt gelezen, en elke regel erin is decoratie.- Het bestand staat op de verkeerde plek of heeft de verkeerde naam. Het moet
.htaccesszijn, met de leidende punt, in de directory waar het verzoek naar wijst. Editors die vriendelijkhtaccess.txtopslaan, zijn een terugkerende oorzaak. - mod_rewrite is niet geladen.
Redirectwerkt,RewriteRuledoet het stilletjes niet, wat mensen een uur naar hun regex laat staren. - Je browser heeft de oude 301 gecachet. Chrome en Firefox cachen permanente redirects allebei agressief, per browserprofiel, waardoor de fix die je net hebt gedeployd voor jou onzichtbaar is en voor iedereen anders prima werkt. Gebruik tijdens de ontwikkeling
R=302en schakel over naarR=301zodra de regel klopt. - De regel matcht zijn eigen doel.
RewriteRule ^(.*)$ /index.php/$1zonder guard is de klassieker. Voeg een conditie toe die de bestemming uitsluit.
Test met curl, niet met de browser
Één commando vertelt je de status, het doel, en hoeveel sprongen het kostte:
curl -sIL https://example.com/old-page | grep -iE '^HTTP|^location'
Lees de output als een sequentie. Twee HTTP/2 301-regels voor de 200 betekent twee sprongen, en elke sprong is een echte round trip voor een echte bezoeker op een mobiel netwerk. Google's documentatie over redirects behandelt een permanente redirect als het sterkste signaal voor het consolideren van een URL, en er in één stap komen is strikt beter dan er in drie komen. Onze linkchecker drukt dezelfde keten af in een browser, en 301 versus 302 redirects behandelt welke status je moet versturen als je het niet zeker weet.
Test de paden die ertoe doen in plaats van de ene die je net hebt geschreven: de root, een diep pad, een pad met een querystring, en het doel zelf. Dat laatste vangt lussen voordat je bezoekers dat doen.
Wanneer je .htaccess helemaal niet moet gebruiken
Apache's eigen standpunt is onmiskenbaar. "Als je toegang hebt tot het hoofdserverconfiguratiebestand, moet je al je configuratie daar zetten in plaats van in .htaccess-bestanden," omdat het parsen per verzoek echt werk kost: "het toestaan van .htaccess-bestanden veroorzaakt een prestatieverlies, of je ze daadwerkelijk gebruikt of niet." Op shared hosting heb je geen keuze. Op een server die je zelf beheert, is de hoofdconfiguratie de betere plek voor alles wat structureel is.
Er is een tweede reden om regels helemaal buiten het bestand te houden, en die heeft niets met prestaties te maken. Redirects die verschijnen in print, in een QR-code, of op de slide deck van iemand anders, moeten je webserver, je CMS-migratie, en mogelijk je hostingprovider overleven. Een regel in .htaccess is één onvoorzichtige deploy verwijderd van verdwijnen, en niemand meldt een dode geprinte link totdat de campagne voorbij is. Structurele redirects horen in de server; campagne- en printlinks horen op een plek die je in seconden kunt bewerken en meten zonder access-logs te doorzoeken.
Lees de cornerstone-serie
Dit artikel valt onder de tutorials-cluster. Voor de volledige kaart behandelt soorten URL-redirects elke statuscode en client-side methode, en een URL redirecten behandelt de zes plekken waar een redirect kan zitten.
Gerelateerd op de blog
Veelgestelde vragen
Hoe maak ik een 301-redirect in .htaccess?
Zet één regel in het .htaccess-bestand in je document root: Redirect 301 /old-page https://example.com/new-page. Apache leest .htaccess bij elk verzoek, dus de redirect is live zodra je het bestand opslaat. Geen restart, geen deploy. Die directive komt van mod_alias, dat op vrijwel elke Apache-installatie is ingeschakeld.
Wat is het verschil tussen Redirect en RewriteRule?
Redirect en RedirectMatch komen van mod_alias en doen één ding: een statuscode en een Location-header versturen. RewriteRule komt van mod_rewrite en kan de host, de querystring, cookies of de user agent inspecteren voordat het beslist. Apache's eigen documentatie zegt dat eenvoudige redirects mod_alias moeten gebruiken in plaats van RewriteRule, en behandelt mod_rewrite als laatste redmiddel.
Waarom werkt mijn .htaccess-redirect niet?
Vijf oorzaken dekken bijna alles: AllowOverride staat op None, waardoor het bestand volledig wordt genegeerd, het bestand staat niet in de document root of heeft de verkeerde naam, mod_rewrite is niet geladen, je browser heeft een eerdere 301 gecachet en vraagt de server nooit meer, of de regel matcht zijn eigen doel en lust. Test met curl in plaats van een browser, want een gecachete 301 laat een gerepareerde regel kapot lijken.
Overleeft de querystring een 301-redirect in .htaccess?
Met Redirect en RedirectMatch: ja, die wordt automatisch meegenomen. Met RewriteRule hangt het antwoord af van de vervanging: geen vraagteken erin en de oorspronkelijke querystring gaat gewoon door, een vraagteken met je eigen parameters vervangt hem, een kaal vraagteken aan het einde wist hem, en de QSA-vlag combineert beide. Dit fout doen laat stilletjes UTM-parameters vallen.
Hoe redirect ik HTTP naar HTTPS en non-www naar www in één sprong?
Gebruik één regel met twee voorwaarden verbonden door OR, die in één stap herschrijft naar het canonieke scheme en de canonieke host. Twee afzonderlijke regelblokken leveren twee redirects op voor iedereen die aankomt op http:// zonder www, en elke extra sprong kost latency en verdunt het signaal. Achter een proxy of CDN test je %{HTTP:X-Forwarded-Proto} in plaats van %{HTTPS}, anders bouw je een lus.
Vertraagt .htaccess een site?
Een beetje, en onvermijdelijk. Apache's documentatie is daar onomwonden over: het toestaan van .htaccess-bestanden veroorzaakt een prestatieverlies, of je ze nu gebruikt of niet, omdat httpd bij elk verzoek in elke directory naar het bestand zoekt. Als je toegang hebt tot de hoofdserverconfiguratie, horen dezelfde regels daar in plaats van in .htaccess, eenmalig geladen bij het opstarten.
Probeer Elido
Plak een URL, krijg een werkende korte link
Geen aanmelding nodig. Link blijft 30 dagen actief. Meld je aan om hem voor altijd te bewaren.
Gratis, geen aanmelding nodig · 2 per dag