Điểm:2

Tại sao chuyển hướng trong .htaccess không hoạt động?

lá cờ sa

Tôi có một trang web Wordpress. Tôi muốn chuyển hướng các url .php sang các url không có hậu tố .php. .htaccess như sau:

# BẮT ĐẦU WordPress
<IfModule mod_rewrite.c>
Viết LạiEngine Trên


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


viết lại cơ sở /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
Quy tắc viết lại . /index.php [L]
</IfModule>

# HẾT WordPress

Nhưng khi tôi đến thăm https://www.example.com/somepage.php, trang không thể hiển thị. Lỗi sau được hiển thị trong trình duyệt:

Trang không chuyển hướng đúng cách

    Đã xảy ra lỗi khi kết nối với www.example.com.
    
        Vấn đề này đôi khi có thể do vô hiệu hóa hoặc từ chối chấp nhận cookie.

Và url trong thanh địa chỉ trở thành https://www.example.com/index.

Nếu tôi thay đổi quy tắc viết lại thành:

# BẮT ĐẦU WordPress
<IfModule mod_rewrite.c>
Viết LạiEngine Trên


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


viết lại cơ sở /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
Quy tắc viết lại . /index.php [L]
</IfModule>

# HẾT WordPress

Và ghé thăm https://www.example.com/somepage.html, nó được chuyển hướng thành công đến https://www.example.com/somepage và trang web được hiển thị bình thường. Tại sao?

Điểm:2
lá cờ kz

Bởi vì, vì chuyển hướng là vô điều kiện, cuối cùng bạn lại chuyển hướng sau đó URL đã được viết lại thành index.php (bộ điều khiển phía trước WordPress).

Khi bạn yêu cầu /somepage.php:

  1. Bạn được chuyển hướng đến /trang nào đó (theo quy tắc đầu tiên). Phản hồi chuyển hướng được gửi lại cho khách hàng.
  2. Ở yêu cầu thứ hai, /trang nào đó được viết lại nội bộ thành /index.php theo quy tắc cuối cùng. Công cụ viết lại sau đó bắt đầu lại (trong một danh mục bối cảnh)...
  3. /index.php được chuyển hướng đến /mục lục (theo quy tắc đầu tiên).Phản hồi chuyển hướng được gửi lại cho khách hàng.
  4. Về yêu cầu thứ ba /mục lục được viết lại nội bộ thành /index.php bởi lần viết lại cuối cùng. Công cụ viết lại sau đó bắt đầu lại ...
  5. Goto 3 (bị mắc kẹt trong một vòng lặp chuyển hướng vô tận).

trong một danh mục bối cảnh (như .htaccess) công cụ viết lại không chỉ thực hiện một lần duy nhất thông qua tập lệnh. Nó lặp lại cho đến khi URL đi qua không thay đổi. (Trừ khi bạn sử dụng CHẤM DỨT cờ trên Apache 2.4 hoặc xảy ra chuyển hướng 3xx bên ngoài.)

Thay đổi để loại bỏ .html hoạt động tốt vì bạn đang viết lại /index.php, mà không kết thúc trong .html, vì vậy chỉ thị chuyển hướng (loại bỏ .html) không phù hợp với.

Để giải quyết vấn đề này, bạn cần tránh chuyển hướng yêu cầu đã viết lại. Bạn có thể làm điều này bằng cách:

  • sử dụng CHẤM DỨT cờ (Apache 2.4+) trong lần viết lại cuối cùng, thay vì l để ngăn chặn bất kỳ vòng lặp nào nữa của công cụ viết lại. Mặc dù bạn nên tránh thay đổi các chỉ thị stock WordPress (xem bên dưới), vì vậy đây có thể không phải là tùy chọn ưu tiên. Điều này cũng không hoạt động trên Apache 2.2.

  • Hoặc, kiểm tra xem .php mở rộng chống lại YÊU CẦU biến máy chủ (chứa dòng đầu tiên của tiêu đề yêu cầu HTTP và không thay đổi khi yêu cầu được viết lại). Ví dụ:

    # Chỉ xóa phần mở rộng ".php" trên các yêu cầu "trực tiếp" (không được viết lại)
    RewriteCond %{THE_REQUEST} [A-Z]{3,7}\s/[^?]+\.php(?:\?|\s|$) [NC]
    RewriteRule (.+)\.php$ /$1 [R=301,L,NC]
    
  • Hoặc, kiểm tra REDIRECT_STATUS biến môi trường, trống trong yêu cầu ban đầu và được đặt thành 200 (như ở trạng thái HTTP 200 OK) trong lần viết lại thành công đầu tiên (điều này đơn giản hơn biểu thức chính quy phức tạp hơn ở trên). Ví dụ:

    # Chỉ xóa phần mở rộng ".php" trên các yêu cầu "trực tiếp" (không được viết lại)
    RewriteCond %{ENV:REDIRECT_STATUS} ^$
    RewriteRule (.+)\.php$ /$1 [R=301,L,NC]
    

Tuy nhiên, bạn không nên chỉnh sửa mã bên trong # BẮT ĐẦU WordPress phần, vì bản thân WordPress cố gắng duy trì điều này và có thể ghi đè lên mã này sau. quy tắc này cần phải đi trước các # BẮT ĐẦU WordPress đánh dấu nhận xét. Bạn không cần phải lặp lại Viết LạiEngine Trên lệnh xuất hiện sau trong tệp (trong phần WordPress).

Bạn sẽ cần xóa bộ nhớ cache của trình duyệt trước khi thử nghiệm, vì chuyển hướng sai (vĩnh viễn) có thể đã được trình duyệt lưu vào bộ nhớ cache. Trước tiên hãy thử nghiệm với chuyển hướng 301 (tạm thời) để tránh các vấn đề về bộ nhớ đệm.

Tuy nhiên, điều này một mình không cho phép bạn truy cập .php tập tin mà không có .php sự mở rộng. Vì URL không có phần mở rộng sẽ cần phải được viết lại nội bộ trở lại .php tập tin.

peter avatar
lá cờ sa
Trong yêu cầu đầu tiên "/somepage.php", sau khi xử lý "RewriteRule ^(.*)\.php$ "$1" [R=301,L,NC]", công cụ viết lại có khởi động lại do url được viết lại "/ somepage" không giống với trang gốc?
lá cờ kz
@peter Trong lần yêu cầu đầu tiên, công cụ viết lại bị chấm dứt ngay lập tức khi chuyển hướng, nó không bắt đầu lại. Trong yêu cầu _thứ hai_, công cụ viết lại "bắt đầu lại" vì URL được viết lại `/index.php` không giống với URL ban đầu (`/somepage`).Có, công cụ viết lại "bắt đầu lại" vì URL bị thay đổi trong quá trình viết lại.
peter avatar
lá cờ sa
vậy làm cách nào để biết liệu công cụ viết lại có bắt đầu lại hay không? Cả hai yêu cầu đều viết lại url thành một url khác, tại sao yêu cầu thứ hai gây ra khởi động lại nhưng yêu cầu đầu tiên thì không?
lá cờ kz
@peter Nếu mã phản hồi 3xx (chuyển hướng bên ngoài) được đặt, thì ở cuối quá trình hiện tại đi qua công cụ viết lại, công cụ viết lại kết thúc và chuyển hướng xảy ra, không có lần chuyển bổ sung nào qua công cụ viết lại trong trường hợp này. Ở trên, quá trình viết lại luôn được kết thúc bởi chuyển hướng. Nếu không có "chuyển hướng" (ví dụ: xóa cờ `R` khỏi quy tắc đầu tiên) thì nó sẽ dẫn đến vòng lặp ghi lại nội bộ (500 Phản hồi Lỗi Máy chủ Nội bộ cho máy khách).
lá cờ kz
Chỉ cần làm rõ, bằng cách "xảy ra chuyển hướng", ý tôi là phản hồi chuyển hướng 3xx được gửi lại cho máy khách (hoàn chỉnh với tiêu đề phản hồi HTTP `Location` với mục tiêu chuyển hướng dự định).
lá cờ kz
@peter Tôi đã cập nhật câu trả lời của mình để hy vọng làm rõ một số điểm (liên quan đến chuyển hướng) và thêm một ví dụ sử dụng `THE_REQUEST` để ngăn vòng lặp chuyển hướng. Mặc dù tôi vẫn nghĩ rằng ví dụ mà tôi đã đăng ban đầu (sử dụng `REDIRECT_STATUS` env var) là giải pháp ưa thích/sạch nhất trong trang web WordPress này.
peter avatar
lá cờ sa
Câu trả lời của bạn rất chi tiết, rõ ràng và hữu ích. Xuất sắc! Cảm ơn rất nhiều!

Đăng câu trả lời

Hầu hết mọi người không hiểu rằng việc đặt nhiều câu hỏi sẽ mở ra cơ hội học hỏi và cải thiện mối quan hệ giữa các cá nhân. Ví dụ, trong các nghiên cứu của Alison, mặc dù mọi người có thể nhớ chính xác có bao nhiêu câu hỏi đã được đặt ra trong các cuộc trò chuyện của họ, nhưng họ không trực giác nhận ra mối liên hệ giữa câu hỏi và sự yêu thích. Qua bốn nghiên cứu, trong đó những người tham gia tự tham gia vào các cuộc trò chuyện hoặc đọc bản ghi lại các cuộc trò chuyện của người khác, mọi người có xu hướng không nhận ra rằng việc đặt câu hỏi sẽ ảnh hưởng—hoặc đã ảnh hưởng—mức độ thân thiện giữa những người đối thoại.