Làm cách nào để xóa tiện ích mở rộng khỏi và buộc dấu gạch chéo ở cuối URL?


7

Ví dụ về cấu trúc tệp hiện tại:

example.com/foo.php  
example.com/bar.html  
example.com/directory/  
example.com/directory/foo.php  
example.com/directory/bar.html  
example.com/cgi-bin/directory/foo.cgi*  

Tôi muốn xóa các phần mở rộng HTML, PHP và CGI khỏi, và sau đó buộc dấu gạch chéo ở cuối URL. Vì vậy, nó có thể trông như thế này:

example.com/foo/  
example.com/bar/  
example.com/directory/  
example.com/directory/foo/  
example.com/directory/bar/  
example.com/cgi-bin/directory/foo/

Tôi rất thất vọng vì tôi đã tìm kiếm 17 giờ liên tục để tìm giải pháp và đã truy cập hơn vài trăm trang trên các blog và diễn đàn khác nhau. Tôi không nói đùa. Vì vậy, tôi nghĩ rằng tôi đã thực hiện nghiên cứu của tôi.

Đây là mã nằm trong tệp .htaccess của tôi ngay bây giờ:

RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}\.html -f
RewriteRule ^(([^/]+/)*[^./]+)/$ $1.html
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !(\.[a-zA-Z0-9]|/)$
RewriteRule (.*)$ /$1/ [R=301,L]

Như bạn có thể thấy, mã này chỉ loại bỏ .html (và tôi không hài lòng lắm với nó vì tôi nghĩ nó có thể được thực hiện đơn giản hơn rất nhiều). Tôi có thể xóa phần mở rộng khỏi các tệp PHP khi tôi đổi tên chúng thành .html thông qua .htaccess, nhưng đó không phải là điều tôi muốn. Tôi muốn loại bỏ nó thẳng. Đây là điều đầu tiên tôi không biết làm.

Điều thứ hai thực sự rất khó chịu. Tệp .htaccess của tôi với mã ở trên, thêm .html/vào mỗi chuỗi được nhập sau example.com/directory/foo/. Vì vậy, nếu tôi nhập example.com/directory/foo/bar(rõ ràng /barkhông tồn tại vì foolà một tệp), thay vì chỉ hiển thị thông báo mà trang đó không được tìm thấy, nó sẽ chuyển đổi thành example.com/directory/foo/bar.html/, sau đó tìm kiếm tệp trong vài giây và sau đó hiển thị thông báo không tìm thấy. Điều này, tất nhiên, là hành vi xấu.

Vì vậy, một lần nữa, tôi cần mã trong .htaccess để làm những việc sau:

  • Xóa phần mở rộng .html
  • Xóa phần mở rộng .php
  • Xóa phần mở rộng .cgi
  • Buộc dấu gạch chéo ở cuối URL
  • Yêu cầu phải hành xử chính xác (không thêm dấu gạch chéo hoặc phần mở rộng vào chuỗi nếu tệp hoặc thư mục không tồn tại trên máy chủ)
  • Mã phải đơn giản nhất có thể

@Kronbernkzion xuất sắc. Vấn đề duy nhất tôi gặp phải bây giờ là 404 dường như không hoạt động đúng và dẫn tôi đến một nơi thực sự thú vị, thậm chí tôi không thể sử dụng chuyển hướng 404 tuyệt đối.

ErrorDocument 404 http://www.google.com

Bạn đã đi qua điều này? Làm thế nào bạn vượt qua nó?

Ngoài việc viết lại 404, mã đầy đủ tôi đã sử dụng là:

<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_URI} (.*)/$
RewriteCond %{REQUEST_FILENAME}\.html -f
RewriteRule (.*)/$ $1.html [L]

RewriteCond %{REQUEST_URI} (.*)/$
RewriteCond %{REQUEST_FILENAME}\.php -f
RewriteRule (.*)/$ $1.php [L]

RewriteCond %{REQUEST_URI} (.*)/$
RewriteCond %{REQUEST_FILENAME}\.cgi -f
RewriteRule (.*)/$ $1.cgi [L]

RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}\.html -f [OR]
RewriteCond %{REQUEST_FILENAME}\.php -f [OR]
RewriteCond %{REQUEST_FILENAME}\.cgi -f
RewriteRule .* %{REQUEST_FILENAME}/ [R=301,L]
</IfModule>

Tôi cảm thấy nỗi đau của bạn
Mark Henderson

Câu hỏi: Các quy tắc viết lại này có cần khớp với TẤT CẢ phần mở rộng không? Ví dụ, nếu bạn có /foo.html/bar.php, thì bạn sẽ có một quy tắc rõ ràng phù hợp /foo/để /foo.html/bar/để /bar.php? Hoặc bạn có cần một mục chung chung phù hợp /foo/với cả /foo.htmlOR /foo.php(tùy thuộc vào mục nào tồn tại) không?
Mark Henderson

Tôi cần một mục chung chung. Không có gì cụ thể về tệp, tôi chỉ muốn xóa tiện ích mở rộng khỏi ba loại tệp đó.

@Kronbernkzion, tôi đã cập nhật câu trả lời của mình. Tôi không nghĩ rằng bạn sẽ thích những gì nó nói mặc dù.
Mark Henderson

Không có lý do thực sự để sử dụng dấu gạch chéo. Nhìn vào zendesk.com, người sử dụng wordpress, họ đã cấu hình permalik của họ để không sử dụng dấu gạch chéo. Tôi cũng đã sử dụng cùng một thiết lập trên một vài tên miền và Google thu thập chúng tốt, và chúng trông IMHO tốt hơn so với dấu gạch chéo. Tôi sẽ nâng cấp lên WP nếu bạn có thể và chỉ cần thiết lập 301 từ các trang tĩnh hoặc động cũ của bạn sang các trang WP mới.
Anagio

Câu trả lời:


6

Vì vậy, tôi đã viết một bộ quy tắc Rewrite đã làm những gì bạn muốn, nhưng nó đã phá vỡ hoàn toàn trang web của tôi. Tôi nhận ra rằng những gì bạn muốn có lẽ không phải là những gì bạn cần. Việc thêm dấu gạch chéo vào cuối tất cả các URL thực sự gây rối với ngữ nghĩa của URL ở chỗ bạn không còn truy cập tệp /foomà là danh sách nội dung của thư mục /foo/.

Ví dụ:

thay đổi /mypageđể /mypage/có thể sẽ phá vỡ bất kỳ liên kết tương đối. Nếu bạn tham chiếu tệp Javascript <script src="myscript.js">, thay vì tìm kiếm /myscript.js, trình duyệt sẽ tìm kiếm /mypage/myscript.js. Bạn sẽ cần thay đổi nguồn của mình để đọc <script src="../myscript.js">cái nào 1) không có ý nghĩa với tác giả và 2) trông xấu hơn so với việc không có dấu gạch chéo.

Để tham khảo:

RewriteCond %{REQUEST_FILE}\.html -f
RewriteRule (.*)$ $1.html [L]

RewriteCond %{REQUEST_FILE}\.php -f
RewriteRule (.*)$ $1.php [L]

RewriteCond %{REQUEST_FILE}\.cgi -f
RewriteRule (.*)$ $1.cgi [L]

sẽ chỉ thay đổi các phần mở rộng php, cgi và html, nhưng một ý tưởng tốt hơn là sử dụng đàm phán nội dung Apache2 (với MultiViews).

Biên tập:

Mã ban đầu. Hoặc ít nhất là một phần của nó. Tôi đã phá vỡ nó, và sau đó cắt nó xuống ở trên, và bây giờ tôi không thể nhớ những gì tôi đã làm. Nhưng nó làm mọi thứ trừ việc loại bỏ các phần mở rộng.

# This block adds the trailing slash
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond /your/web/directory%{REQUEST_URI}\.html -f [OR]
RewriteCond /your/web/directory%{REQUEST_URI}\.php -f [OR]
RewriteCond /your/web/directory%{REQUEST_URI}\.cgi -f
RewriteRule .* %{REQUEST_URI}/ [R=301,L]

# These blocks redirect /foo/ to /foo.html and so on
RewriteCond %{REQUEST_URI} (.*)/$
RewriteCond /your/web/directory%1\.html -f
RewriteRule (.*)/$ $1.html [L]

RewriteCond %{REQUEST_URI} (.*)/$
RewriteCond /your/web/directory%1\.php -f
RewriteRule (.*)/$ $1.php [L]

RewriteCond %{REQUEST_URI} (.*)/$
RewriteCond /your/web/directory%1\.cgi -f
RewriteRule (.*)/$ $1.cgi [L]

Bạn có thể gửi email cho tôi tại mazin (at) aztekera.com nếu bạn muốn.


Tôi biết chính xác những gì tôi cần. Thẩm mỹ và chức năng của dấu gạch chéo trong URL là chủ đề cho chính nó, vì vậy chúng tôi sẽ không đi sâu vào vấn đề đó. Không phải lo lắng về việc phá vỡ liên kết vì tôi đang trong quá trình xây dựng trang web từ đầu.

Bạn sẽ thêm gì vào đoạn mã trên để buộc dấu gạch chéo ở cuối URL?

OK, tôi đã thêm hầu hết những gì tôi có. Tôi vẫn nghĩ rằng bạn đang đi sai đường bằng cách buộc các dấu gạch chéo cho rằng nó phá vỡ ngữ nghĩa của đường dẫn, nhưng bạn có vẻ khá quyết tâm.

3

Mazin, cảm ơn bạn rất nhiều vì sự giúp đỡ của bạn và đã chỉ cho tôi hướng đi đúng đắn! Mã dưới đây hoạt động để loại bỏ các phần mở rộng .html, .php và .cgi cũng như để buộc các dấu gạch chéo vào cuối URL. Mã làm việc cuối cùng trông như thế này:

RewriteCond %{REQUEST_URI} (.*)/$
RewriteCond %{REQUEST_FILENAME}\.html -f
RewriteRule (.*)/$ $1.html [L]

RewriteCond %{REQUEST_URI} (.*)/$
RewriteCond %{REQUEST_FILENAME}\.php -f
RewriteRule (.*)/$ $1.php [L]

RewriteCond %{REQUEST_URI} (.*)/$
RewriteCond %{REQUEST_FILENAME}\.cgi -f
RewriteRule (.*)/$ $1.cgi [L]

RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}\.html -f [OR]
RewriteCond %{REQUEST_FILENAME}\.php -f [OR]
RewriteCond %{REQUEST_FILENAME}\.cgi -f
RewriteRule .* %{REQUEST_FILENAME}/ [R=301,L]

Tôi vô cùng hạnh phúc với cách này.

Tôi đã gửi một thẻ quà tặng iTunes $ 50 đến Mazin như một lời cảm ơn lớn vì đã giúp đỡ.


1

Có vẻ như bạn đang cố gắng làm điều gì đó tương tự như việc triển khai URL tuân thủ REST.

Tôi đã thấy điều này được đề cập trước đây trên SO, tại đây: /programming/395650/url-mapping-in-php

Bạn có thể thích ứng với 2 giải pháp hàng đầu theo nhu cầu của bạn.


Như tôi đã nói ở trên, tôi không quan tâm đến việc làm nó với PHP.

0

Nếu bạn biết định dạng chính xác của từng URL mà bạn cần, thì nó khá dễ dàng. Nếu bạn không biết phần mở rộng nào bạn cần phải khớp, thì tôi chắc chắn điều đó là không thể.

Ví dụ: nếu bạn BIẾT rằng bạn có foo.htmlbar.php- và điều đó /foo/cần khớp với foo.html và bạn BIẾT rằng /bar/ cần phải khớp /bar.php, thì điều đó có thể được thực hiện. Nhưng, nếu ai đó tải lên /cat.phpvà ai đó vào /cat/- hệ thống sẽ không biết liệu nó có cần khớp /cat.htmlhay không /cat.php- bạn cần nói với nó. Nếu bạn chỉ giao dịch với một tiện ích mở rộng, điều đó sẽ không tệ lắm, bạn có thể giải quyết nó theo mọi yêu cầu.

Để viết lại /foo/để /foo.htmlsau đó bạn sẽ làm gì:

RewriteRule (/foo/) /foo.html

Dễ dàng

Nếu bạn muốn khớp mọi yêu cầu với tiện ích mở rộng SINGLE, thì bạn có thể làm:

RewriteRule (/foo/)(.*)(/) /foo/$2.html

Điều này sẽ ánh xạ /foo/mypage/tới /foo/mypage.html(và bạn có thể mở rộng thư mục này sang thư mục đa cấp bằng cách sử dụng một số RegEx-fu cao hơn mức lương của tôi).

Bây giờ, tôi thực sự không biết rằng đó là những gì bạn đang yêu cầu, vì vậy hãy nhận xét câu trả lời của tôi hoặc cập nhật câu hỏi của bạn, nếu những quy tắc này sẽ không hiệu quả với bạn.

-- Biên tập --

Chỉ cần nhận thấy phản ứng của bạn với nhận xét của tôi ở trên. Không có cách nào bạn có thể làm những gì bạn muốn làm với .htaccess, bởi vì .htaccess không có khả năng kiểm tra xem có tồn tại một yêu cầu tệp cụ thể nào không. Làm thế nào nó sẽ biết đó /foo/có nghĩa là /foo.htmlhoặc /foo.phphay /foo.cgi? Cách duy nhất của bạn xung quanh nó sẽ là:

1) Kênh MERYI yêu cầu thông qua một tệp tin.php có khả năng biết / kiểm tra xem phiên bản .php hoặc .html hoặc .cgi của tệp có tồn tại không, và sau đó chuyển tiếp yêu cầu của bạn theo cách đó

2) Tạo tệp .htaccess chứa mục nhập cho mỗi tệp duy nhất


Tôi sẽ không có tên tệp trùng lặp, vì vậy sẽ không bao giờ có foo.html và foo.php, vì vậy Apache sẽ không cần phải quyết định tệp nào sẽ được phục vụ.

Trả lời chỉnh sửa của bạn: Một lần nữa, tất cả những gì tôi cần làm là xóa mọi phần mở rộng .html, .php và .cgi và sau đó thêm một dấu gạch chéo dấu gạch chéo. Tôi không có nghi ngờ rằng điều này có thể được thực hiện. Tôi biết nó có thể dễ dàng được thực hiện thông qua tệp PHP và tôi biết rất nhiều người thích phương pháp này, nhưng tôi muốn thực hiện nó thông qua .htaccess.

Có hay không có tên tệp trùng lặp hay không là không liên quan. Apache sẽ không biết bạn là ai, kể cả phục vụ nó. Bạn sẽ cần một hệ thống với một số thông minh mà bạn có thể lập trình các quy tắc của mình thành để nó biết nội dung nào sẽ phục vụ. Tùy chọn đó là PHP hoặc ASP. Đây là những gì chúng tôi đã làm khi chúng tôi ở trong một tình huống tương tự. Chúng tôi đã chuyển MỌI yêu cầu vào một tệp .php, sau đó đóng vai trò là proxy của chúng tôi. Sau đó, tệp PHP sẽ truy vấn từng phiên bản của URL cho đến khi tìm thấy một phiên bản không trả về trạng thái 404 và sau đó nó sẽ phân phát nội dung đó ra trình duyệt.
Đánh dấu Henderson

Xin lỗi, chỉ cần xem bình luận của bạn - phải được viết trong khi tôi đang viết của tôi. Điều này không thể được thực hiện bởi .htaccess - nó đơn giản là một nhiệm vụ quá phức tạp đối với công cụ viết lại đơn giản của nó.
Mark Henderson

Vì vậy, bạn đang nói rằng nó chỉ có thể xử lý một phần mở rộng loại tệp. Nó chỉ có thể là .html hoặc chỉ .php, nó không thể làm cả hai? Bạn có chắc chắn về điều đó không?
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.