O redirecționare 301 în .htaccess este o singură linie:
Redirect 301 /old-page https://example.com/new-page
Salvează asta în fișierul .htaccess de la rădăcina documentelor tale, și este activă imediat. Apache citește fișierul la fiecare cerere, așa că nu există niciun restart și niciun deploy. Directiva vine din mod_alias, care este prezentă pe practic orice instalare Apache, și trimite un 301 Moved Permanently cu un header Location. Asta este toată treaba.
Aproape tot ce merge greșit cu redirecționările Apache se întâmplă după acest punct: recurgerea la RewriteRule când Redirect ar fi suficient, mixarea celor două module într-un singur fișier și obținerea unei ordini la care nimeni nu se aștepta, sau pierderea query string-ului pe parcurs. Acest articol acoperă cele patru reguli care merită memorate, capcana ordinii de execuție care face ca fișiere care par corecte să se comporte greșit, și cum testezi o redirecționare fără ca browserul tău să te mintă. Pentru imaginea de ansamblu a locurilor unde pot exista redirecționări, vezi cum redirecționezi un URL.
Linia unică care acoperă majoritatea redirecționărilor
Redirect primește un status, o cale de potrivit, și o țintă. Ținta poate fi un URL complet sau o cale pe același host:
Redirect 301 /old-page /new-page
Redirect 301 /shop https://shop.example.com/
RedirectMatch 301 ^/blog/([0-9]{4})/(.*)$ /articles/$2
Merită să știi două comportamente înainte să îl folosești. Primul, îndrumarea proprie a Apache este explicită că acesta este instrumentul potrivit: "Acest tip de redirecționare simplă a unui URL, sau a unei clase de URL-uri, către altundeva, ar trebui realizat folosind aceste directive, nu RewriteRule."
Al doilea, și acesta surprinde oamenii: "Ține minte că Redirect păstrează informația de cale. Cu alte cuvinte, o redirecționare pentru un URL /one va redirecționa și toate URL-urile de sub acesta, cum ar fi /one/two.html și /one/three/four.html." Dacă vrei doar calea exactă, RedirectMatch 301 ^/one$ o ancorează. În caz contrar, ai redirecționat un întreg subarbore, ceea ce este câteodată exact ce ai vrut și câteodată o dimineață foarte confuză.
RedirectMatch este versiunea cu regex, și acoperă cea mai mare parte din ceea ce oamenii deschid mod_rewrite pentru. Grupurile capturate ajung în $1, $2, și așa mai departe, așa că o redenumire de director sau o schimbare de schemă de URL bazată pe dată este o singură linie.
Când ai de fapt nevoie de RewriteRule
Recurge la mod_rewrite atunci când decizia depinde de altceva decât calea. Host-ul, query string-ul, metoda cererii, cookie-urile, și user agent-ul sunt toate vizibile pentru RewriteCond și invizibile pentru Redirect:
RewriteEngine On
RewriteCond %{QUERY_STRING} (^|&)ref=oldpartner(&|$)
RewriteRule ^landing$ /partners/oldpartner? [R=301,L]
Există o capcană în contextul per-director care explică o mare parte din regulile copy-paste care nu fac absolut nimic. Apache elimină prefixul directorului înainte de potrivire, așa că modelul nu vede niciodată o bară oblică la început: "Prefixul eliminat se termină întotdeauna cu o bară oblică, ceea ce înseamnă că potrivirea are loc pe un șir care nu are niciodată o bară oblică la început. Prin urmare, un Pattern cu ^/ nu se potrivește niciodată în context per-director."
De aceea RewriteRule ^/old$ /new [R=301] funcționează atunci când cineva îl lipește într-un virtual host, dar dă greș pe tăcute în .htaccess. Elimină bara oblică: ^old$. Când substituția ta este o cale relativă și rescrierea se află într-un subdirector, poate ai nevoie și de RewriteBase pentru a-i spune Apache față de ce sunt relative căile.
Capcana ordinii de execuție
Aceasta este cea care îi costă pe oameni o după-amiază. Poziția liniei în fișier nu decide care modul rulează primul.
Apache documentează asta clar: "Dacă totuși mixezi Redirect și RewriteRule în același context, fii conștient că ordinea lor de execuție depinde de locul în care apar. În contextul server/virtual-host, mod_rewrite rulează primul; în contextul per-director (.htaccess), mod_alias rulează primul."
Citește asta de două ori, pentru că consecința este contraintuitivă. Într-un fișier .htaccess, un Redirect de la finalul fișierului bate un RewriteRule de la început. Mută regulile identice într-un virtual host, și câștigătorul se inversează. Flag-ul [L] nu te salvează nici el: înseamnă ultima regulă din această trecere a mod_rewrite, nu ultima regulă din fișier, și nu are nicio autoritate asupra altui modul.
Regula practică pe care o urmez: un modul per fișier. Dacă un proiect are nevoie de condiții undeva, fă toate redirecționările lui cu mod_rewrite și șterge liniile Redirect. Fișierele mixte sunt de unde vin rapoartele de bug care spun "redirecționarea funcționează pe staging, dar nu în producție", pentru că cele două medii pun regulile în contexte diferite.
Query string-uri: păstrate, înlocuite, sau șterse
Linkurile de marketing trăiesc și mor prin query string-urile lor, așa că acest tabel merită afișat la vedere. Totul este comportament documentat, nu folclor.
| Ce scrii | Query string-ul original | Note |
|---|---|---|
Redirect 301 /a /b | Transportat | mod_alias îl adaugă pentru tine |
RedirectMatch 301 ^/a$ /b | Transportat | Același modul, același comportament |
RewriteRule ^a$ /b [R=301] | Trece nemodificat | Comportamentul documentat implicit |
RewriteRule ^a$ /b?src=x [R=301] | Înlocuit cu al tău | Parametrii tăi câștigă |
RewriteRule ^a$ /b?src=x [R=301,QSA] | Combinat cu al tău | QSA adaugă originalul |
RewriteRule ^a$ /b? [R=301] | Șters | Un ? gol îl elimină |
Formularea Apache despre comportamentul implicit: "În mod implicit, query string-ul trece nemodificat." Iar despre flag-uri, [QSA] "adaugă orice query string din URL-ul cererii originale la orice query string creat în ținta rescrierii", în timp ce [QSD] elimină pe cel primit. Dacă redirecționezi către un URI absolut, query string-ul vine odată cu el, cu excepția cazului în care ceri [QSD].
Defectarea pe care asta o previne este silențioasă și costisitoare. O regulă care înlocuiește query string-ul elimină utm_source și utm_campaign pe parcurs, analiza ta atribuie sesiunea traficului direct, și nimic nu dă eroare. Nimeni nu observă până când cineva întreabă de ce campania de primăvară nu a primit niciun credit. Parametrii UTM care nu apar în GA4 acoperă diagnosticul din partea analizei.
Dacă te trezești întreținând zeci de redirecționări de campanie într-un fișier de configurare al serverului, acesta este un semnal, nu o corvoadă. Regulile de server au nevoie de un deploy, de o revizuire a configurației Apache, și de cineva cu acces shell. Mută linkurile de campanie pe linkuri scurte pe care le poți edita singur și păstrează .htaccess pentru redirecționările structurale la care este bun.
HTTPS și www într-un singur hop, nu în două
Cel mai copiat fragment de pe internet face asta în două blocuri de reguli, ceea ce înseamnă că un vizitator care ajunge la http://example.com/page este redirecționat de două ori: o dată pentru a adăuga TLS, o dată pentru a adăuga www. Două hop-uri, două drumuri dus-întors, și un semnal puțin mai slab la fiecare.
O regulă, două condiții, un hop:
RewriteEngine On
RewriteCond %{HTTPS} !=on [OR]
RewriteCond %{HTTP_HOST} !^www\.example\.com$ [NC]
RewriteRule ^ https://www.example.com%{REQUEST_URI} [R=301,L]
În spatele unui CDN sau al unui load balancer, %{HTTPS} este de obicei off la origine, chiar și atunci când vizitatorul este pe HTTPS, pentru că TLS s-a terminat mai sus în lanț. Testează %{HTTP:X-Forwarded-Proto} în schimb:
RewriteCond %{HTTP:X-Forwarded-Proto} !https
Greșește asta și construiești o buclă infinită de redirecționare: proxy-ul trimite HTTPS, originea crede că este HTTP, redirecționează către HTTPS, și tot așa, până când browserul renunță. Cum repari o buclă de redirecționare trece prin diagnosticarea asta din headerele răspunsului.
De ce nu funcționează
În ordinea în care le verific:
AllowOverrideesteNone. Documentația Apache afirmă comportamentul implicit: "Aceasta înseamnă că fișierele.htaccesssunt complet ignorate, cu excepția cazului în care le activezi explicit pentru un director." Testează asta punând deliberat gunoi pe prima linie. Absența unei erori 500 înseamnă că fișierul tău nu este citit deloc, și fiecare regulă din el este decorativă.- Fișierul este poziționat greșit sau denumit greșit. Trebuie să fie
.htaccess, cu punctul de la început, în directorul spre care se mapează cererea. Editoarele care salvează "util" cahtaccess.txtsunt o cauză recurentă. - mod_rewrite nu este încărcat.
Redirectfuncționează,RewriteRulenu, în tăcere, ceea ce îi trimite pe oameni să se uite la regex-ul lor timp de o oră. - Browserul tău a memorat vechiul 301. Chrome și Firefox memorează amândouă redirecționările permanente agresiv, per profil de browser, așa că fix-ul pe care l-ai deployat acum este invizibil pentru tine, dar funcționează bine pentru toți ceilalți. În timpul dezvoltării, folosește
R=302și trece laR=301odată ce regula este corectă. - Regula se potrivește cu propria țintă.
RewriteRule ^(.*)$ /index.php/$1fără o gardă este clasicul. Adaugă o condiție care exceptează destinația.
Testează cu curl, nu cu browserul
O singură comandă îți spune statusul, ținta, și câte hop-uri a durat:
curl -sIL https://example.com/old-page | grep -iE '^HTTP|^location'
Citește rezultatul ca o secvență. Două linii HTTP/2 301 înainte de 200 înseamnă două hop-uri, și fiecare hop este un drum dus-întors real pentru un vizitator real pe o rețea mobilă. Documentația Google despre redirecționări tratează o redirecționare permanentă ca cel mai puternic semnal pentru consolidarea unui URL, și a ajunge acolo într-un singur pas este strict mai bine decât a ajunge acolo în trei. Verificatorul nostru de linkuri afișează același lanț într-un browser, și 301 vs 302: redirecționări acoperă ce status să trimiți când nu ești sigur.
Testează căile care contează, nu doar pe cea pe care ai scris-o acum: rădăcina, o cale profundă, o cale cu un query string, și ținta însăși. Ultima prinde buclele înainte ca vizitatorii tăi să o facă.
Când să nu folosești deloc .htaccess
Poziția proprie a Apache este lipsită de ambiguitate. "Dacă ai acces la fișierul principal de configurare a serverului, ar trebui să pui toată configurația ta acolo, în loc de fișiere .htaccess," pentru că analiza per-cerere costă muncă reală: "permiterea fișierelor .htaccess cauzează o penalizare de performanță, indiferent dacă le folosești de fapt sau nu." Pe hosting partajat nu ai de ales. Pe un server pe care îl controlezi, configurația principală este locul mai bun pentru orice este structural.
Există un al doilea motiv pentru a ține regulile complet în afara fișierului, și nu are nimic de-a face cu performanța. Redirecționările care apar în tipar, într-un cod QR, sau pe prezentarea altcuiva, trebuie să supraviețuiască serverului tău web, migrării CMS-ului tău, și posibil furnizorului tău de hosting. O regulă din .htaccess este la un deploy neatent distanță de a dispărea, și nimeni nu raportează un link tipărit mort până când campania s-a terminat. Redirecționările structurale își au locul pe server; linkurile de campanie și de tipar își au locul undeva unde le poți edita în câteva secunde și le poți măsura fără să cauți prin access log-uri.
Citește seria fundamentală
Acest articol face parte din clusterul tutorials. Pentru harta completă, tipuri de redirecționări acoperă fiecare cod de status și metodă client-side, iar cum redirecționezi un URL acoperă cele șase locuri în care poate exista o redirecționare.
Alte articole de pe blog
Întrebări frecvente
Cum creez o redirecționare 301 în .htaccess?
Pune o linie în fișierul .htaccess de la rădăcina documentelor tale: Redirect 301 /old-page https://example.com/new-page. Apache citește .htaccess la fiecare cerere, așa că redirecționarea este activă în momentul în care salvezi fișierul. Fără restart, fără deploy. Directiva respectivă vine din mod_alias, care este activat pe practic orice instalare Apache.
Care este diferența dintre Redirect și RewriteRule?
Redirect și RedirectMatch vin din mod_alias și fac un singur lucru: trimit un cod de status și un header Location. RewriteRule vine din mod_rewrite și poate inspecta host-ul, query string-ul, cookie-urile, sau user agent-ul înainte să decidă. Documentația proprie a Apache spune că redirecționarea simplă ar trebui să folosească mod_alias, nu RewriteRule, și tratează mod_rewrite ca ultimă soluție.
De ce nu funcționează redirecționarea mea din .htaccess?
Cinci cauze acoperă aproape tot: AllowOverride este None, așa că fișierul este ignorat complet, fișierul nu este la rădăcina documentelor sau este denumit greșit, mod_rewrite nu este încărcat, browserul tău a memorat un 301 anterior și nu mai întreabă niciodată serverul din nou, sau regula se potrivește cu propria țintă și face buclă. Testează cu curl, nu cu un browser, pentru că un 301 memorat face ca o regulă corectă să pară stricată.
Supraviețuiește query string-ul unei redirecționări 301 în .htaccess?
Cu Redirect și RedirectMatch, da, este transportat automat. Cu RewriteRule, răspunsul depinde de substituție: fără semn de întrebare în ea, și query string-ul original trece nemodificat; un semn de întrebare și propriii tăi parametri îl înlocuiesc; un semn de întrebare gol la final îl șterge; iar flag-ul QSA combină ambele. Greșirea acestui lucru elimină în tăcere parametrii UTM.
Cum redirecționez HTTP către HTTPS și non-www către www într-un singur hop?
Folosește o singură regulă cu două condiții unite prin OR, rescriind spre schema și host-ul canonice într-un singur pas. Două blocuri de reguli separate produc două redirecționări pentru orice vizitator care ajunge pe http:// fără www, și fiecare hop suplimentar costă latență și diluează semnalul. În spatele unui proxy sau CDN, testează %{HTTP:X-Forwarded-Proto} în loc de %{HTTPS}, altfel vei construi o buclă.
Încetinește .htaccess un site?
Puțin, și inevitabil. Documentația Apache este directă în privința asta: permiterea fișierelor .htaccess cauzează o penalizare de performanță, indiferent dacă le folosești sau nu, pentru că httpd caută fișierul în fiecare director la fiecare cerere. Dacă ai acces la configurația principală a serverului, aceleași reguli ar trebui să fie acolo, încărcate o singură dată la pornire.
Încearcă Elido
Lipește un URL, obții un link scurt funcțional
Fără înregistrare. Linkul este activ timp de 30 de zile. Înregistrează-te ca să-l păstrezi pentru totdeauna.
Gratuit, fără înregistrare · 2 pe zi