Mengapa saya mendapatkan garis miring ganda tergantung di mana RewriteRule saya berada?

9

Saya menggunakan kode berikut untuk mengarahkan semua permintaan www ke URL non-www:

RewriteEngine On
RewriteCond %{HTTP_HOST} ^www\.example\.org$ [NC]
RewriteRule ^(.*)$ http://example.com/$1 [R=301,L]

Ini berfungsi baik di dalam file .htaccess di root situs web saya.
Misalnya,
www.example.com -> example.com/
www.example.com/ -> example.com/
www.example.com/other_page -> example.com/other_page

Namun, jika saya memindahkan kode yang sama ini ke konfigurasi VirtualHost saya, URL yang ditulis ulang berisi slash trailing ganda.
www.example.com -> example.com//
www.example.com/ -> example.com//
www.example.com/other_page -> example.com//other_page

Saya memperbaikinya dengan menghapus garis miring dari aturan penulisan ulang:

RewriteEngine On
RewriteCond %{HTTP_HOST} ^www\.example\.org$ [NC]
RewriteRule ^(.*)$ http://example.com$1 [R=301,L]

Tapi saya tidak bisa mengerti alasannya. Adakah yang tahu kenapa?

davekaro
sumber

Jawaban:

10

Seperti yang saya pahami, dalam file .htaccess, string yang diproses oleh mod_rewrite dalam aturan Anda relatif terhadap direktori tempat file .htaccess berada, sehingga tidak akan memiliki / pada awalnya.

Dalam entri VirtualHost, string yang diprosesnya mutlak ke root server, dan termasuk juga /.

Itu membuat perbedaan halus dalam cara mod_rewrite bekerja.

Inilah seseorang dengan masalah yang serupa, dan solusinya:

http://forum.modrewrite.com/viewtopic.php?p=56322&sid=77f72967f59200b5b5de174440234c3a

Ini harus bekerja dalam kedua kasus, dengan asumsi saya ingat saya melarikan diri dengan benar:

RewriteEngine On
RewriteCond %{HTTP_HOST} ^www\.example\.org$ [NC]
RewriteRule ^\/?(.*?)$ http://example.com/$1 [R=301,L]
Neobyte
sumber
Terima kasih! Sekarang saya mengerti mengapa, setidaknya. Namun, apakah ini lebih baik karena beberapa alasan daripada hanya menghapus / sebelum $ 1 seperti yang saya tunjukkan dalam pertanyaan awal saya?
davekaro
1
Tidak ada yang lebih baik atau lebih buruk, itu hanya sebuah blok yang dapat Anda tukarkan antara .htaccess dari VirtualHost tanpa harus mengeditnya setiap kali untuk menangani perbedaan konteks. Jika cara Anda bekerja untuk Anda, tetaplah menggunakannya! :)
Neobyte
Oh itu benar - metode Anda akan bekerja di .htaccess dan VirtualHost. Itu membuatnya lebih baik IMO :)
davekaro
4
Saya memiliki masalah yang sama persis dengan @davekaro dan mencoba solusi Anda. Baris terakhir tidak berhasil untuk saya. RewriteRule ^/?(.*)$ http://example.com/$1 [R=301,L]melakukan trik.
Kenny Rasschaert
2

Ini terjadi karena Anda menangkap tebasan awal dengan (.*) dan kemudian menerapkan garis miring lain sebelum di garis miring yang baru /$1. Itu tidak terjadi sebelumnya karena mod_rewrite berperilaku sedikit berbeda ketika beroperasi dalam konteks per-direktori yang bertentangan dengan konteks per-server.

Anda bisa menghindari ini dengan melakukan pre-empting slash. Selain itu Anda dapat menggunakan RedirectMatch di VirtualHost kosong dengan domain kelebihan Anda, yang membuat pemrosesan lebih sedikit dan dapat terlihat lebih bersih.

<VirtualHost *>
ServerName example.com
ServerAlias other.example.com
..
RedirectMatch permanent ^/?(.*) http://example.com/$1
</VirtualHost>

Dan Carley
sumber
Bagus. Saya suka pendekatan RedirectMatch. Saya mungkin akan menggunakan ini karena itu benar-benar pengalihan yang ingin saya capai.
davekaro
1

Saya menyertakan posting ini untuk kelengkapan.

The dokumentasi Apache menjelaskan mengapa perilaku ini terjadi sangat baik dan merupakan alasan bahwa 'RewriteBase' direktif ada.

Cukup dengan memasukkan arahan 'RewriteBase' dalam file .htaccess Anda akan mencapai hasil yang Anda inginkan.

Contoh:

RewriteEngine On
RewriteBase /
RewriteCond %{HTTP_HOST} ^www\.example\.org$ [NC]
RewriteRule ^(.*)$ http://example.com/$1 [R=301,L]

Dari dokumentasi Apache 2.2 mod_rewrite:

Arahan RewriteBase secara eksplisit menetapkan URL dasar untuk penulisan ulang per-direktori.

Aturan praktis saya adalah hampir selalu menggunakan 'RewriteBase' dalam file .htaccess, dan tidak menggunakannya dalam konfigurasi Apache.


sumber
0

Saya tidak punya waktu untuk menangani masalah ini jadi tulis ulang // ke / :)

RewriteCond %{THE_REQUEST} //
RewriteRule ^(.*)$ http://domain.com [R=301,L]
pengguna956584
sumber