Tại sao tôi nhận được một dấu gạch chéo kép tùy thuộc vào vị trí RewriteRule của tôi nằm ở đâu?


9

Tôi đang sử dụng mã sau đây để hướng tất cả các yêu cầu www đến các URL không phải www:

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

Điều này hoạt động rất tốt trong một tập tin .htaccess trong thư mục gốc của trang web của tôi.
Ví dụ:
www.example.com -> example.com/
www.example.com/ -> example.com/
www.example.com/other_page -> example.com/other_page

Tuy nhiên, nếu tôi di chuyển cùng mã này vào cấu hình Virtualhost của mình, các URL được viết lại chứa một dấu gạch chéo kép.
www.example.com -> example.com//
www.example.com/ -> example.com//
www.example.com/other_page -> example.com//other_page

Tôi đã sửa nó bằng cách xóa dấu gạch chéo khỏi quy tắc viết lại:

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

Nhưng tôi không thể hiểu lý do cho việc này. Có ai biết tại sao không?

Câu trả lời:


10

Theo tôi hiểu, trong các tệp .htaccess, chuỗi mà mod_rewrite xử lý trong quy tắc của bạn có liên quan đến thư mục tệp .htaccess nằm trong, vì vậy nó sẽ không có / khi bắt đầu.

Trong mục Virtualhost, chuỗi mà nó xử lý là tuyệt đối với thư mục gốc của máy chủ và do đó bao gồm /.

Nó tạo ra sự khác biệt tinh tế trong cách mod_rewrite hoạt động.

Đây là một người có vấn đề tương tự và giải pháp:

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

Điều này sẽ hoạt động trong cả hai trường hợp, giả sử tôi nhớ chính xác việc trốn thoát của mình:

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

Cảm ơn! Bây giờ tôi hiểu tại sao, ít nhất. Tuy nhiên, điều này có tốt hơn vì một số lý do hơn là chỉ xóa / trước $ 1 như tôi hiển thị trong câu hỏi ban đầu của mình không?
davekaro

1
Không tốt hơn hay tệ hơn, nó chỉ là một khối mà bạn có thể trao đổi giữa .htaccess của Virtualhost mà không phải chỉnh sửa mỗi lần để xử lý các khác biệt về ngữ cảnh. Nếu cách của bạn làm việc cho bạn, hãy gắn bó với nó! :)
Neobyte

Ồ đúng rồi - phương pháp của bạn sẽ hoạt động trong cả .htaccess và Virtualhost. Điều đó làm cho IMO tốt hơn :)
davekaro

4
Tôi đã có cùng một vấn đề chính xác như @davekaro và đã thử giải pháp của bạn. Dòng cuối cùng không làm việc cho tôi. RewriteRule ^/?(.*)$ http://example.com/$1 [R=301,L]đã lừa
Kenny Rasschaert

2

Nó đang xảy ra bởi vì bạn đang bắt một dấu gạch chéo ban đầu (.*)và sau đó áp dụng một dấu gạch chéo khác trước nó ở vị trí mới /$1. Điều đó đã không xảy ra trước đây vì mod_rewrite hoạt động hơi khác khi hoạt động trong bối cảnh mỗi thư mục trái ngược với bối cảnh trên mỗi máy chủ.

Bạn có thể tránh điều này bằng cách tùy ý xóa dấu gạch chéo. Ngoài ra, bạn có thể sử dụng RedirectMatch trong một Virtualhost trống với các tên miền dư thừa của bạn, điều này tạo ra một chút xử lý và có thể trông gọn gàng hơn.

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


Đẹp. Tôi thích cách tiếp cận RedirectMatch. Tôi có thể sẽ đi với điều này vì nó thực sự là một chuyển hướng mà tôi muốn thực hiện.
davekaro

1

Tôi đang bao gồm bài viết này cho đầy đủ.

Các tài liệu Apache giải thích tại sao hành vi này xảy ra rất tốt và là lý do rằng 'RewriteBase' chỉ tồn tại.

Chỉ cần bao gồm lệnh 'RewriteBase' trong tệp .htaccess của bạn sẽ đạt được kết quả mong muốn của bạn.

Thí dụ:

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

Từ tài liệu mod_rewrite của Apache 2.2:

Lệnh RewriteBase đặt rõ ràng URL cơ sở cho các lần ghi lại trên mỗi thư mục.

Nguyên tắc nhỏ của tôi là hầu như luôn sử dụng 'RewriteBase' trong các tệp .htaccess và không sử dụng nó trong cấu hình Apache.


0

Tôi không có thời gian để xử lý vấn đề này nên chỉ cần viết lại // thành / :)

RewriteCond %{THE_REQUEST} //
RewriteRule ^(.*)$ http://domain.com [R=301,L]
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.