.HTACCESS Membuat Rantai Pengalihan 301 yang Tidak Perlu - Bagaimana Cara Menghapusnya?

Jan 12 2020

Tumpukan Saya:

  • LAMPU
  • Apache / 2.4.41

Informasi latar belakang:

Saya baru saja meluncurkan situs web baru untuk klien. Selama proses desain ulang kami memutuskan untuk:

  • Beralih ke HTTPS di seluruh situs
  • Hapus ekstensi .php dari URL
  • Beralih ke CMS

Contoh URL LAMA:
http://www.example.com/courses/acme-course.php

Contoh URL BARU:
https://www.example.com/courses/acme-course

Masalah Saya:

Pengalihan 301 tambahan yang tidak perlu terjadi saat pengguna menavigasi ke salah satu URL LAMA.

Saya tidak mengerti mengapa pengalihan 301 tambahan dibuat dan tidak mengarahkan pengguna langsung ke URL tujuan yang benar menggunakan satu pengalihan 301.

Pengamatan Menarik:

Pengalihan 301 tambahan yang tidak perlu tidak terjadi saat saya menggunakan URL LAMA dengan HTTPS, bukan HTTP.

Contoh:
https://www.example.com/courses/acme-course.php _

Menggunakan URL di atas dengan benar akan melakukan Pengalihan 301 dengan benar ke URL tujuan yang benar dari: https://www.example.com/courses/acme-course

Inilah Contoh 301 Redirect Chain:

URL Permintaan Asli:

http://www.example.com/courses/acme-course.php

1ST 301 Redirect (Tidak Diperlukan):

DARI:

http://www.example.com/courses/acme-course.php

UNTUK:

https://www.example.com/index.php?url=courses/acme-course.php

2ND 301 Redirect (Benar URL Tujuan Akhir):

DARI:

https://www.example.com/index.php?url=courses/acme-course.php

UNTUK:

https://www.example.com/courses/acme-course

Kode .htaccess saya:

# (1) General Settings
<IfModule mod_rewrite.c>
    Options +FollowSymLinks
    RewriteEngine On
</IfModule>

# (2) Force WWW
<IfModule mod_rewrite.c>
    RewriteCond %{HTTPS} !=off
    RewriteCond %{HTTP_HOST} !^www\. [NC]
    RewriteCond %{SERVER_ADDR} !=127.0.0.1
    RewriteCond %{SERVER_ADDR} !=::1
    RewriteRule ^ %{ENV:PROTO}://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
</IfModule>

# (3) Force HTTPS
<IfModule mod_rewrite.c>
    RewriteCond %{HTTPS} !=on
    RewriteRule ^(.*)$ https://%{HTTP_HOST}/$1 [R=301,L]
</IfModule>

# (4) URL Routing for CMS
<IfModule mod_rewrite.c>

    RewriteCond %{HTTPS} =on
    RewriteRule ^ - [env=proto:https]
    RewriteCond %{HTTPS} !=on
    RewriteRule ^ - [env=proto:http]

    ## Check if file/directory exists
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d

    ## Route all other URLs to index.php/URL
    RewriteRule ^(.*)$ index.php?url=$1 [PT,L,QSA]
</IfModule>

Jawaban

MrWhite Jan 12 2020 at 02:19

Anda memiliki dua masalah utama ....

  1. Urutan Anda berada dalam urutan yang salah dalam .htaccessfile. HTTP ke HTTPS dan wwwpengalihan kanonis harus dilakukan sebelum pengontrol depan yang merutekan URL ke CMS Anda. Karenanya, pengalihan eksternal yang salah menjadi /index.php?url=courses/acme-course.php- memperlihatkan struktur URL CMS internal Anda.
  1. Penghapusan .phpsebenarnya tidak dilakukan atas .htaccessperintah Anda ?! Saya berasumsi ini harus dilakukan oleh aplikasi / logika CMS Anda? Akibatnya, ini akan selalu menghasilkan pengalihan kedua (karena .htaccessmengalihkan ke HTTPS di jalur URL yang sama). Anda perlu melakukan sesuatu seperti berikut di bagian atas .htaccessfile Anda untuk menghapus .phpekstensi.

    RewriteRule (.+)\.php$ https://www.example.com/$1 [R=301,L]
    

UPDATE: Jika saya menyusun ulang aturan / ketentuan, apakah penempatan Options + FollowSymlinks saya tetap sama?

Ini tidak benar-benar peduli di mana para Optionsdirektif terjadi. Namun, logis (dari sudut pandang keterbacaan) untuk menempatkannya di dekat bagian atas. (Perintah Apache tidak harus dijalankan sesuai urutan kemunculannya di file konfigurasi, karena setiap modul bekerja secara independen.)

Dengan asumsi Anda mengkodekan .htaccessfile Anda secara manual, maka file itu dapat dirapikan ...

  1. Tidak diperlukan <IfModule mod_rewrite.c>pembungkus (multipel) . Apakah mod_rewrite opsional? Apakah situs Anda di-porting ke beberapa server di mana mod_rewrite tidak diaktifkan?

  2. Tidak perlu banyak RewriteEnginearahan. Contoh terakhir benar - benar menang dan mengontrol seluruh file.

    Banyak <IfModule>blok dan RewriteEnginetipikal sistem yang secara otomatis diedit oleh kode dan / atau dirancang untuk berfungsi tanpa diedit di beberapa server.

Jadi, .htaccessfile Anda harus ditulis ulang seperti ini dalam urutan ini:

Options +FollowSymlinks

# Enable the rewrite engine...   
RewriteEngine On

# ----------------------------------------------------------------------
# | Forcing `https://`                                                       |
# ----------------------------------------------------------------------

# Redirect to HTTPS on the "same host" (requirement for HSTS)
RewriteCond %{HTTPS} !=on
RewriteRule (.*) https://%{HTTP_HOST}/$1 [R=301,L] # ---------------------------------------------------------------------- # | Forcing `www` | # ---------------------------------------------------------------------- RewriteCond %{HTTP_HOST} !^www\. RewriteCond %{SERVER_ADDR} !=127.0.0.1 RewriteCond %{SERVER_ADDR} !=::1 RewriteRule ^ https://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L] # ---------------------------------------------------------------------- # | URL Routing for CMS | # ---------------------------------------------------------------------- # (3) RewriteCond %{HTTPS} =on RewriteRule ^ - [env=proto:https] RewriteCond %{HTTPS} !=on RewriteRule ^ - [env=proto:http] # (4) - Check if physical file exists RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d # (5) - Rewrite all other URLs to index.php/URL RewriteRule (.*) index.php?url=$1 [L,QSA]

Catatan tambahan:

  • The PROTOvariabel lingkungan mengandung protokol apa pun yang sedang diminta. Dengan urutan pengalihan, ini sekarang akan selalu menjadi HTTPS. Alasan untuk variabel ini adalah agar CMS dapat mengalihkan ke HTTP jika HTTP diakses, atau HTTPS jika HTTPS diakses. Jika Anda memaksakan HTTPS maka itu tidak benar-benar berlaku. (Meskipun env var ini masih dapat digunakan oleh aplikasi Anda.)

  • Jarang sekali Anda menggunakan NCbendera pada kondisi yang dinegasikan. Karenanya mengapa saya menghapusnya dari kondisi tersebut !^www\.. Anda ingin mengalihkan ketika host tidak dimulai dengan www.- semua huruf kecil. Dengan NCbendera itu akan gagal untuk mengalihkan WwW.- meskipun ini akan sangat jarang.

  • Saya telah menghapus pemeriksaan yang tidak perlu untuk HTTPS di pengalihan kanonik www.

  • The PTbendera pada yang terakhir RewriteRuletidak diperlukan dalam .htaccess. Dalam .htaccesshal ini adalah perilaku default (melewati).

  • Anda perlu membersihkan cache browser Anda sebelum menguji, karena pengalihan 301 yang salah kemungkinan besar telah di-cache oleh browser. Sebaiknya uji dengan 302 pengalihan (sementara) karena alasan ini.