Puncte:2

De ce redirecționarea în .htaccess nu funcționează?

drapel sa

Am un site Wordpress. Vreau să redirecționez adresele URL .php către cele fără sufixul .php. .htaccess este după cum urmează:

# ÎNCEPE WordPress
<IfModule mod_rewrite.c>
RewriteEngine Pornit


RewriteRule ^(.*)\.php$ „$1” [R=301,L,NC]


RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>

# Terminați WordPress

Dar când mă vizitez https://www.example.com/somepage.php, pagina nu poate fi afișată. Următoarea eroare este afișată în browser:

Pagina nu redirecționează corect

    A apărut o eroare în timpul conexiunii la www.example.com.
    
        Această problemă poate fi uneori cauzată de dezactivarea sau refuzul de a accepta cookie-uri.

Și url-ul din bara de adrese devine https://www.example.com/index.

Dacă schimb regula de rescriere ca:

# ÎNCEPE WordPress
<IfModule mod_rewrite.c>
RewriteEngine Pornit


RewriteRule ^(.*)\.html$ „$1” [R=301,L,NC]


RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>

# Terminați WordPress

Și vizitează https://www.example.com/somepage.html, este redirecționat cu succes către https://www.example.com/somepage iar pagina web este afișată normal. De ce?

Puncte:2
drapel kz

Pentru că, din moment ce redirecționarea este necondiţionat, ajungi să redirecționezi din nou după URL-ul a fost rescris index.php (controlerul frontal WordPress).

Când solicitați /somepage.php:

  1. Sunteți redirecționat către /pe o pagină (prin prima regulă). Răspunsul de redirecționare este trimis înapoi clientului.
  2. La a doua cerere, /pe o pagină este rescris intern la /index.php după ultima regulă. Motorul de rescriere pornește apoi de la capăt (în a director context)...
  3. /index.php este redirecționat către /index (prin prima regulă).Răspunsul de redirecționare este trimis înapoi clientului.
  4. La a treia cerere /index este rescris intern la /index.php prin ultima rescriere. Motorul de rescriere pornește apoi de la capăt...
  5. Treci la 3 (blocat într-o buclă de redirecționare fără sfârșit).

Într-o director context (cum ar fi .htaccess) motorul de rescriere nu face pur și simplu o singură trecere prin script. Se face buclă până când URL-ul trece neschimbat. (Cu excepția cazului în care utilizați Sfârşit flag pe Apache 2.4 sau apare o redirecționare externă 3xx.)

Se schimbă pentru a elimina .html funcționează OK pentru că rescrieți în /index.php, care nu se termină în .html, deci directiva de redirecționare (care elimină .html) nu se potrivește.

Pentru a rezolva acest lucru, trebuie să evitați redirecționarea cererii rescrise. Puteți face acest lucru prin:

  • folosind Sfârşit flag (Apache 2.4+) la ultima rescriere, în loc de L pentru a preveni alte bucle ale motorului de rescrire. Deși ar trebui să evitați modificarea directivelor WordPress stoc (vezi mai jos), așa că aceasta poate să nu fie opțiunea preferată. Acest lucru nu funcționează nici pe Apache 2.2.

  • Sau, verificați pentru .php prelungire împotriva CEREREA variabila server (care conține linia inițială a antetelor cererii HTTP și nu se modifică atunci când cererea este rescrisă). De exemplu:

    # Eliminați extensia „.php” numai pentru cererile „directe” (nu rescrise).
    RewriteCond %{THE_REQUEST} [A-Z]{3,7}\s/[^?]+\.php(?:\?|\s|$) [NC]
    RewriteRule (.+)\.php$ /$1 [R=301,L,NC]
    
  • Sau, verificați REDIRECT_STATUS variabilă de mediu, care este goală la cererea inițială și setată la 200 (ca în starea HTTP 200 OK) la prima rescriere reușită (aceasta este mai simplă decât expresia regex destul de complexă de mai sus). De exemplu:

    # Eliminați extensia „.php” numai pentru cererile „directe” (nu rescrise).
    RewriteCond %{ENV:REDIRECT_STATUS} ^$
    RewriteRule (.+)\.php$ /$1 [R=301,L,NC]
    

Cu toate acestea, nu ar trebui să editați codul din interiorul # ÎNCEPE WordPress secțiunea, deoarece WordPress însuși încearcă să mențină acest lucru și poate suprascrie acest cod mai târziu. Această regulă trebuie să meargă inainte de cel # ÎNCEPE WordPress marcator de comentarii. Nu trebuie să repetați RewriteEngine Pornit directivă care apare mai târziu în fișier (în secțiunea WordPress).

Va trebui să ștergeți memoria cache a browserului înainte de testare, deoarece redirecționarea eronată (permanentă) va fi probabil memorată în cache de browser. Testați mai întâi cu redirecționări 301 (temporare) pentru a evita problemele de stocare în cache.

Cu toate acestea, numai acest lucru nu vă permite să accesați .php fișiere fără .php extensie. Deoarece adresa URL fără extensie va trebui rescrisă intern înapoi la .php fişier.

peter avatar
drapel sa
În timpul primei solicitări „/somepage.php”, după procesarea „RewriteRule ^(.*)\.php$ „$1” [R=301,L,NC]”, motorul de rescriere pornește de la capăt deoarece url-ul rescris „/ somepage" nu este același cu cel original?
drapel kz
@peter În timpul primei solicitări, motorul de rescriere se oprește imediat la redirecționare, nu pornește de la capăt. În timpul celei de-a doua solicitări, motorul de rescriere „pornește de la capăt”, deoarece URL-ul rescris `/index.php` nu este același cu originalul (`/somepage`).Da, motorul de rescrire „pornește de la capăt”, deoarece adresa URL este schimbată în timpul procesului de rescrire.
peter avatar
drapel sa
deci, cum pot spune dacă motorul de rescrire va porni de la capăt sau nu? Cele două solicitări rescriu ambele url-ul într-un alt alt, de ce a doua cerere provoacă pornirea de la capăt, dar prima solicitare nu?
drapel kz
@peter Dacă este setat un cod de răspuns 3xx (redirecționare externă), atunci la sfârșitul trecerii curente prin motorul de rescrire, motorul de rescrire se termină și are loc redirecționarea, nu există treceri suplimentare prin motorul de rescrire în acest caz. În cele de mai sus, procesul de rescriere este întotdeauna încheiat de redirecționare. Dacă nu a existat nicio „redirecționare” (de exemplu, eliminați steag-ul `R` din prima regulă), atunci va avea ca rezultat o buclă de rescriere internă (răspunsul de 500 Eroare de server intern la client).
drapel kz
Doar pentru a clarifica, prin „are loc redirecționarea”, vreau să spun că răspunsul de redirecționare 3xx este trimis înapoi către client (complet cu antetul răspunsului HTTP `Locație` cu ținta de redirecționare intenționată).
drapel kz
@peter Mi-am actualizat răspunsul pentru a clarifica unele puncte (referitor la redirecționare) și am adăugat un exemplu care folosește `THE_REQUEST` pentru a preveni bucla de redirecționare. Deși tot cred că exemplul pe care l-am postat inițial (folosind `REDIRECT_STATUS` env var) este soluția preferată/curată din acest site WordPress.
peter avatar
drapel sa
Răspunsul tău este foarte detaliat, clar și util. Excelent! Mulțumesc mult!

Postează un răspuns

Majoritatea oamenilor nu înțeleg că a pune multe întrebări deblochează învățarea și îmbunătățește legătura interpersonală. În studiile lui Alison, de exemplu, deși oamenii își puteau aminti cu exactitate câte întrebări au fost puse în conversațiile lor, ei nu au intuit legătura dintre întrebări și apreciere. În patru studii, în care participanții au fost implicați în conversații ei înșiși sau au citit transcrieri ale conversațiilor altora, oamenii au avut tendința să nu realizeze că întrebarea ar influența – sau ar fi influențat – nivelul de prietenie dintre conversatori.