Chuyển hướng, thay đổi URL hoặc chuyển hướng HTTP sang HTTPS trong Apache - Mọi thứ bạn từng muốn biết về Quy tắc Mod_Rewrite nhưng lại ngại hỏi


264

Đây là một câu hỏi Canonical về mod_rewrite của Apache.

Thay đổi URL yêu cầu hoặc chuyển hướng người dùng sang một URL khác với URL họ yêu cầu ban đầu được thực hiện bằng mod_rewrite. Điều này bao gồm những thứ như:

  • Thay đổi HTTP thành HTTPS (hoặc ngược lại)
  • Thay đổi yêu cầu thành một trang không còn tồn tại để thay thế mới.
  • Sửa đổi định dạng URL (chẳng hạn như? Id = 3433 thành / id / 3433)
  • Trình bày một trang khác dựa trên trình duyệt, dựa trên người giới thiệu, dựa trên bất cứ điều gì có thể dưới ánh trăng và mặt trời.
  • Bất cứ điều gì bạn muốn làm rối tung với URL

Mọi thứ bạn từng muốn biết về Quy tắc Mod_Rewrite nhưng lại ngại hỏi!

Làm thế nào tôi có thể trở thành một chuyên gia viết các quy tắc mod_rewrite?

  • Định dạng và cấu trúc cơ bản của quy tắc mod_rewrite là gì?
  • Tôi cần phải có hình thức / hương vị của biểu thức chính quy nào?
  • Những sai lầm / cạm bẫy phổ biến nhất khi viết quy tắc viết lại là gì?
  • Phương pháp tốt để kiểm tra và xác minh quy tắc mod_rewrite là gì?
  • Có ý nghĩa SEO hoặc hiệu suất của các quy tắc mod_rewrite mà tôi nên biết không?
  • Có những tình huống phổ biến trong đó mod_rewrite có vẻ như là công cụ phù hợp cho công việc nhưng không?
  • Một số ví dụ phổ biến là gì?

Một nơi để kiểm tra các quy tắc của bạn

Trang web thử nghiệm htaccess là một nơi tuyệt vời để chơi xung quanh với các quy tắc của bạn và kiểm tra chúng. Nó thậm chí còn hiển thị đầu ra gỡ lỗi để bạn có thể thấy những gì phù hợp và những gì không.


9
Ý tưởng đằng sau câu hỏi này là đưa ra một đường dẫn chặt chẽ cho tất cả các câu hỏi mod_rewrite vô tận khiến người dùng thường xuyên hơn của chúng ta phát điên. Điều này rất giống với những gì đã được thực hiện với mạng con tại serverfault.com/questions/49765/how-does-subnetting-work .
Kyle Brandt

1
Ngoài ra, tôi không thực sự muốn có quá nhiều câu hỏi về câu hỏi này , thay vào đó họ nên đi đến câu trả lời. Tôi không muốn CW điều này bởi vì tôi muốn đảm bảo rằng người đăng có được tín dụng đầy đủ cho điều tôi hy vọng là câu trả lời mod_rewrite để kết thúc tất cả các câu hỏi mod_rewrite .
Kyle Brandt

4
Xin lỗi, tôi nêu lên câu hỏi. ;-) Tôi thực sự nghĩ rằng nó cần hiển thị ở (hoặc gần) đầu mod-rewritetìm kiếm / bộ lọc thẻ.
Steven Thứ Hai

Ai đó khác (tm) nên xử lý các trường hợp sử dụng phổ biến. Tôi không biết họ đủ tốt để làm điều đó công lý.
sysadmin1138

Có lẽ câu hỏi này nên được liên kết vào wiki thẻ viết lại để làm cho đường dẫn thậm chí ngắn hơn.
beldaz

Câu trả lời:


224

thứ tự cú pháp mod_rewrite

mod_rewrite có một số quy tắc đặt hàng cụ thể ảnh hưởng đến việc xử lý. Trước khi mọi thứ được thực hiện, lệnh RewriteEngine Onnày cần được đưa ra khi điều này bật xử lý mod_rewrite. Điều này nên được trước khi bất kỳ chỉ thị viết lại khác.

RewriteCondtrước đó RewriteRulelàm cho MỘT quy tắc phải tuân theo điều kiện. Bất kỳ RewriteRules nào sau đây sẽ được xử lý như thể chúng không phải chịu các điều kiện.

RewriteEngine On
RewriteCond %{HTTP_REFERER}          ^https?://serverfault\.com(/|$)
RewriteRule $/blog/(.*)\.html        $/blog/$1.sf.html

Trong trường hợp đơn giản này, nếu người giới thiệu HTTP đến từ serverfault.com, hãy chuyển hướng yêu cầu blog đến các trang serverfault đặc biệt (chúng tôi chỉ đặc biệt như vậy). Tuy nhiên, nếu khối trên có thêm dòng RewriteRule:

RewriteEngine On
RewriteCond %{HTTP_REFERER}          ^https?://serverfault\.com(/|$)
RewriteRule $/blog/(.*)\.html        $/blog/$1.sf.html
RewriteRule $/blog/(.*)\.jpg         $/blog/$1.sf.jpg

Tất cả các tệp .jpg sẽ chuyển đến các trang serverfault đặc biệt, không chỉ các tệp có tham chiếu cho biết nó đến từ đây. Đây rõ ràng không phải là mục đích của cách các quy tắc này được viết. Nó có thể được thực hiện với nhiều quy tắc RewriteCond:

RewriteEngine On
RewriteCond %{HTTP_REFERER}          ^https?://serverfault\.com(/|$)
RewriteRule ^/blog/(.*)\.html        /blog/$1.sf.html
RewriteCond %{HTTP_REFERER}          ^https?://serverfault\.com(/|$)
RewriteRule ^/blog/(.*)\.jpg         /blog/$1.sf.jpg

Nhưng có lẽ nên được thực hiện với một số cú pháp thay thế phức tạp hơn.

RewriteEngine On
RewriteCond %{HTTP_REFERER}                ^https?://serverfault\.com(/|$)
RewriteRule ^/blog/(.*)\.(html|jpg)        /blog/$1.sf.$2

RewriteRule phức tạp hơn chứa các điều kiện để xử lý. Dấu ngoặc đơn cuối cùng, báo (html|jpg)cho RewriteRule khớp với một trong hai htmlhoặc jpgđể biểu diễn chuỗi khớp với giá trị $ 2 trong chuỗi được viết lại. Điều này giống hệt với khối trước đó, với hai cặp RewriteCond / RewriteRule, nó chỉ thực hiện trên hai dòng thay vì bốn.

Nhiều dòng RewriteCond được ngầm định ANDed và có thể được ORed rõ ràng. Để xử lý các tham chiếu từ cả ServerFault và Super User (OR rõ ràng):

RewriteEngine On
RewriteCond %{HTTP_REFERER}                ^https?://serverfault\.com(/|$)    [OR]
RewriteCond %{HTTP_REFERER}                ^https?://superuser\.com(/|$)
RewriteRule ^/blog/(.*)\.(html|jpg)        /blog/$1.sf.$2

Để phục vụ các trang được giới thiệu ServerFault bằng trình duyệt Chrome (ẩn AND):

RewriteEngine On
RewriteCond %{HTTP_REFERER}                ^https?://serverfault\.com(/|$)
RewriteCond %{HTTP_USER_AGENT}             ^Mozilla.*Chrome.*$
RewriteRule ^/blog/(.*)\.(html|jpg)        /blog/$1.sf.$2

RewriteBasecũng là thứ tự cụ thể vì nó chỉ định cách các lệnh sau RewriteRulexử lý việc xử lý của chúng. Nó rất hữu ích trong các tập tin .htaccess. Nếu được sử dụng, nó sẽ là lệnh đầu tiên trong "RewriteEngine on" trong tệp .htaccess. Lấy ví dụ này:

RewriteEngine On
RewriteBase /blog
RewriteCond %{HTTP_REFERER}           ^https?://serverfault\.com(/|$)
RewriteRule ^(.*)\.(html|jpg)         $1.sf.$2

Điều này nói với mod_rewrite rằng URL cụ thể này hiện đang xử lý đã được gửi đến bằng cách http://example.com/blog/ thay vì đường dẫn thư mục vật lý (/ home / $ Username / public_html / blog) và để xử lý nó phù hợp. Bởi vì điều này, RewriteRulecoi đó là chuỗi bắt đầu sau "/ blog" trong URL. Đây là cùng một điều viết hai cách khác nhau. Một cái có RewriteBase, cái kia không có:

RewriteEngine On

##Example 1: No RewriteBase##
RewriteCond %{HTTP_REFERER}                                   ^https?://serverfault\.com(/|$)
RewriteRule /home/assdr/public_html/blog/(.*)\.(html|jpg)     $1.sf.$2

##Example 2: With RewriteBase##
RewriteBase /blog
RewriteCond %{HTTP_REFERER}           ^https?://serverfault\.com(/|$)
RewriteRule ^(.*)\.(html|jpg)         $1.sf.$2

Như bạn có thể thấy, RewriteBasecho phép viết lại các quy tắc để tận dụng đường dẫn của trang web vào nội dung thay vì máy chủ web , điều này có thể khiến chúng trở nên dễ hiểu hơn đối với những người chỉnh sửa các tệp đó. Ngoài ra, họ có thể làm cho các chỉ thị ngắn hơn, có một sự hấp dẫn thẩm mỹ.


Cú pháp kết hợp RewriteRule

RewriteRule tự nó có một cú pháp phức tạp để khớp chuỗi. Tôi sẽ che các cờ (những thứ như [PT]) trong phần khác. Bởi vì Sysadmin học bằng ví dụ thường xuyên hơn bằng cách đọc một trang người đàn ông, tôi sẽ đưa ra ví dụ và giải thích những gì họ làm.

RewriteRule ^/blog/(.*)$    /newblog/$1

Cấu .*trúc khớp với bất kỳ ký tự đơn ( .) nào hoặc nhiều lần ( *). Việc đóng nó trong ngoặc đơn bảo nó cung cấp chuỗi được khớp với biến $ 1.

RewriteRule ^/blog/.*/(.*)$  /newblog/$1

Trong trường hợp này, đầu tiên. * KHÔNG được đặt trong parens nên không được cung cấp cho chuỗi viết lại. Quy tắc này loại bỏ một cấp thư mục trên trang blog mới. (/blog/2009/sample.html trở thành /newblog/sample.html).

RewriteRule ^/blog/(2008|2009)/(.*)$   /newblog/$2

Trong trường hợp này, biểu thức dấu ngoặc đơn đầu tiên thiết lập một nhóm khớp. Điều này trở thành $ 1, không cần thiết và do đó không được sử dụng trong chuỗi viết lại.

RewriteRule ^/blog/(2008|2009)/(.*)$   /newblog/$1/$2

Trong trường hợp này, chúng tôi sử dụng $ 1 trong chuỗi viết lại.

RewriteRule ^/blog/(20[0-9][0-9])/(.*)$   /newblog/$1/$2

Quy tắc này sử dụng cú pháp khung đặc biệt chỉ định phạm vi ký tự . [0-9] khớp với các chữ số từ 0 đến 9. Quy tắc cụ thể này sẽ xử lý các năm từ 2000 đến 2099.

RewriteRule ^/blog/(20[0-9]{2})/(.*)$  /newblog/$1/$2

Điều này thực hiện tương tự như quy tắc trước đó, nhưng phần {2} bảo nó khớp với ký tự trước đó (một biểu thức ngoặc trong trường hợp này) hai lần.

RewriteRule ^/blog/([0-9]{4})/([a-z]*)\.html   /newblog/$1/$2.shtml

Trường hợp này sẽ khớp với bất kỳ chữ cái viết thường nào trong biểu thức khớp thứ hai và làm như vậy cho càng nhiều ký tự càng tốt. Cấu \.trúc bảo nó coi khoảng thời gian là một khoảng thời gian thực tế, không phải là ký tự đặc biệt trong các ví dụ trước. Tuy nhiên, nó sẽ bị hỏng nếu tên tệp có dấu gạch ngang trong đó.

RewriteRule ^/blog/([0-9]{4})/([-a-z]*)\.html  /newblog/$1/$2.shtml

Cái bẫy này đặt tên tệp với dấu gạch ngang trong đó. Tuy nhiên, như -là một ký tự đặc biệt trong biểu thức ngoặc, nó phải là ký tự đầu tiên trong biểu thức.

RewriteRule ^/blog/([0-9]{4})/([-0-9a-zA-Z]*)\.html   /newblog/$1/$2.shtml

Phiên bản này bẫy bất kỳ tên tệp nào bằng chữ cái, số hoặc -ký tự trong tên tệp. Đây là cách bạn chỉ định nhiều bộ ký tự trong biểu thức ngoặc.


Cờ RewriteRule

Các cờ trên quy tắc viết lại có một loạt các ý nghĩa đặc biệt và usecase .

RewriteRule ^/blog/([0-9]{4})/([-a-z]*).\html  /newblog/$1/$2.shtml  [L]

Cờ là phần [L]cuối của biểu thức trên. Nhiều cờ có thể được sử dụng, phân tách bằng dấu phẩy. Các tài liệu được liên kết mô tả từng cái, nhưng dù sao thì đây là:

L = Lần cuối. Dừng xử lý RewriteRules khi cái này khớp. Số lượng đặt hàng!
C = Chuỗi. Tiếp tục xử lý RewriteRule tiếp theo. Nếu quy tắc này không khớp, quy tắc tiếp theo sẽ không được thực thi. Thêm về điều này sau.
E = Đặt biến môi trường. Apache có các biến môi trường khác nhau có thể ảnh hưởng đến hành vi của máy chủ web.
F = Cấm. Trả về lỗi 403-Cấm nếu quy tắc này phù hợp.
G = Đã qua rồi. Trả về lỗi 410-Gone nếu quy tắc này phù hợp.
H = Xử lý. Buộc yêu cầu được xử lý như thể đó là loại MIME được chỉ định.
N = Tiếp theo. Buộc quy tắc bắt đầu lại từ đầu và khớp lại. HÃY CẨN THẬN! Vòng lặp có thể dẫn đến.
NC = Không có trường hợp. Cho phépjpgđể phù hợp với cả jpg và JPG.
NE = Không lối thoát. Ngăn chặn việc viết lại các ký tự đặc biệt (.? # & Vv) thành các mã tương đương mã hex của chúng.
NS = Không có cuộc chinh phục. Nếu bạn đang sử dụng bao gồm phía máy chủ, điều này sẽ ngăn các kết quả khớp với các tệp được bao gồm.
P = Proxy. Buộc quy tắc được xử lý bởi mod_proxy. Cung cấp nội dung một cách minh bạch từ các máy chủ khác, bởi vì máy chủ web của bạn tìm nạp nó và phục vụ lại nó. Đây là một lá cờ nguy hiểm, vì một lá cờ được viết kém sẽ biến máy chủ web của bạn thành một proxy mở và Điều đó thật tệ.
PT = Đi qua. Hãy tính đến các câu lệnh Bí danh trong kết hợp RewriteRule.
QSA = QSAppend. Khi chuỗi gốc chứa truy vấn ( http://example.com/thing?asp=foo) nối chuỗi truy vấn ban đầu vào chuỗi viết lại. Thông thường nó sẽ bị loại bỏ. Quan trọng đối với nội dung động.
R = Chuyển hướng. Cung cấp chuyển hướng HTTP đến URL được chỉ định. Cũng có thể cung cấp mã chuyển hướng chính xác [R = 303]. Rất giống với RedirectMatch, nhanh hơn và nên được sử dụng khi có thể.
S = Bỏ qua. Bỏ qua quy tắc này.
T = Loại. Chỉ định loại mime của nội dung được trả về. Rất giống với AddTypechỉ thị.

Bạn biết làm thế nào tôi nói rằng RewriteCondáp dụng cho một và chỉ một quy tắc? Chà, bạn có thể vượt qua điều đó bằng cách xâu chuỗi.

RewriteEngine On
RewriteCond %{HTTP_REFERER}          ^https?://serverfault\.com(/|$)
RewriteRule ^/blog/(.*)\.html        /blog/$1.sf.html     [C]
RewriteRule ^/blog/(.*)\.jpg         /blog/$1.sf.jpg

Vì RewriteRule đầu tiên có cờ Chain, quy tắc ghi lại thứ hai sẽ thực thi khi lần đầu tiên thực hiện, đó là khi quy tắc RewriteCond trước đó được khớp. Tiện dụng nếu các biểu thức chính quy của Apache làm cho não của bạn bị tổn thương. Tuy nhiên, phương pháp tất cả trong một dòng tôi chỉ đến trong phần đầu tiên nhanh hơn từ quan điểm tối ưu hóa.

RewriteRule ^/blog/([0-9]{4})/([-0-9a-zA-Z]*)\.html   /newblog/$1/$2.shtml

Điều này có thể được thực hiện đơn giản hơn thông qua các cờ:

RewriteRule ^/blog/([0-9]{4})/([-0-9a-z]*)\.html   /newblog/$1/$2.shtml   [NC]

Ngoài ra, một số cờ cũng áp dụng cho RewriteCond. Đáng chú ý là NoCase.

RewriteCond %{HTTP_REFERER}        ^https?://serverfault\.com(/|$)     [NC]

Sẽ khớp với "ServerFault.com"


9
Làm tốt. [phụ]
EEAA

3
Rất đẹp mod_rewritevà regex primer. +1.
Steven Thứ Hai

3
Đó là đôi khi hữu ích để biết rằng RewriteCondthực sự là xử lý sau khi các RewriteRulelà lần xuất hiện. Bạn có thể muốn nói "nhiều hơn về điều đó sau" ở gần đầu nơi bạn nói "RewriteCond trước RewriteRule làm cho quy tắc ONE đó phải tuân theo điều kiện." Bạn có thể muốn đề cập rằng các biểu thức chính là biểu thức chính quy tương thích với Perl. Ngoài ra, bạn có dấu nháy đơn ngoại lai trong "... RewriteRule coi đó là chuỗi bắt đầu ..."
Dennis Williamson

2
RewriteRule ^/blog/.*/(.*)$ /newblog/$1không phù hợp với thành phần thư mục đầu tiên - mặc định là viết lại tham lam. /.*/(.*) khớp với cả / 1 / (2) / và / 1/2/3/4/5 / (6) /, vì vậy bạn cần / [^ /] * / để chỉ khớp với đường dẫn FIRST thành phần.
thích nghi

1
@ sysadmin1138, tôi nghĩ câu trả lời này là tốt nhưng sẽ tốt hơn nếu bạn giải thích nhiều hơn về các cờ E, N, NS, P, PT và S với các ví dụ vì những lá cờ đó không rõ ràng về cách chúng hoạt động, v.v.
Pacerier

39

Định dạng và cấu trúc cơ bản của quy tắc mod_rewrite là gì?

Tôi sẽ trì hoãn câu trả lời tuyệt vời của sysadmin1138 về những điểm này.

Tôi cần phải có hình thức / hương vị của biểu thức chính quy nào?

Ngoài thứ tự cú pháp, khớp cú pháp / biểu thức chính quy và cờ RewriteRule được phác thảo bởi sysadmin1138, tôi tin rằng nó đề cập đến việc mod_rewrite phơi bày các biến môi trường Apache dựa trên tiêu đề yêu cầu HTTP và cấu hình của Apache.

Tôi muốn giới thiệu Hướng dẫn gỡ lỗi mod_rewrite của AskApache cho danh sách toàn diện các biến có thể có sẵn cho mod_rewrite.

Những sai lầm / cạm bẫy phổ biến nhất khi viết quy tắc viết lại là gì?

Hầu hết các vấn đề với RewriteRule bắt nguồn từ sự hiểu lầm về cú pháp / lỗi PCRE để thoát đúng các ký tự đặc biệt hoặc thiếu hiểu biết về nội dung của biến được sử dụng để khớp.

Các sự cố điển hình và đề nghị khắc phục sự cố:

  • 500 - Lỗi máy chủ nội bộ - Loại bỏ các điều khiển vận chuyển Windows trong (các) tệp cấu hình nếu có, đảm bảo mod_rewrite được bật (gói chỉ thị trong IfModuleđiều kiện để tránh trường hợp này), kiểm tra cú pháp chỉ thị, nhận xét chỉ thị cho đến khi xác định được sự cố
  • Vòng lặp chuyển hướng - Sử dụng RewriteLog và RewriteLogLevel, nhận xét các chỉ thị cho đến khi vấn đề được xác định

Phương pháp tốt để kiểm tra và xác minh quy tắc mod_rewrite là gì?

Trước tiên, hãy xem nội dung của (các) biến môi trường mà bạn dự định đối sánh - nếu bạn đã cài đặt PHP, việc này cũng đơn giản như thêm khối sau vào ứng dụng của bạn:

<?php
  var_dump($_SERVER);
?>

... sau đó viết các quy tắc của bạn (tốt nhất là để thử nghiệm trên máy chủ phát triển) và lưu ý mọi hoạt động hoặc kết hợp không nhất quán trong tệp Apache ErrorLog của bạn .

Đối với các quy tắc phức tạp hơn, hãy sử dụng RewriteLogchỉ thị của mod_rewrite để ghi nhật ký hoạt động vào một tệp và đặtRewriteLogLevel 3

Có ý nghĩa SEO hoặc hiệu suất của các quy tắc mod_rewrite mà tôi nên biết không?

AllowOverride alltác động đến hiệu suất của máy chủ vì Apache phải kiểm tra .htaccesscác tệp và phân tích các lệnh theo từng yêu cầu - nếu có thể, hãy giữ tất cả các chỉ thị trong cấu hình Virtualhost cho trang web của bạn hoặc .htaccesschỉ cho phép ghi đè lên các thư mục cần chúng.

Nguyên tắc quản trị trang web của Google tuyên bố rõ ràng: "Đừng lừa dối người dùng của bạn hoặc trình bày nội dung khác nhau cho các công cụ tìm kiếm so với hiển thị cho người dùng, thường được gọi là 'che giấu.'" - tránh tạo ra các chỉ thị mod_rewrite để lọc cho robot công cụ tìm kiếm.

Robot công cụ tìm kiếm thích nội dung 1: 1: ánh xạ URI (đây là cơ sở để xếp hạng các liên kết đến nội dung) - nếu bạn đang sử dụng mod_rewrite để tạo chuyển hướng tạm thời hoặc bạn đang phục vụ cùng một nội dung trong nhiều URI, hãy xem xét chỉ định URI chính tắc trong tài liệu HTML của bạn.

Có những tình huống phổ biến trong đó mod_rewrite có vẻ như là công cụ phù hợp cho công việc nhưng không?

Đây là một chủ đề rất lớn (và có khả năng gây tranh cãi) theo cách riêng của mình - tốt hơn (IMHO) để giải quyết việc sử dụng trên cơ sở từng trường hợp cụ thể và để người hỏi xác định xem các nghị quyết được đề xuất có phù hợp với nhu cầu của họ hay không.

Một số ví dụ phổ biến là gì?

Các mẹo và mẹo về mod_rewrite của AskApache chỉ đề cập đến mọi trường hợp sử dụng phổ biến thường xuyên xuất hiện, tuy nhiên, giải pháp "chính xác" cho một người dùng nhất định có thể phụ thuộc vào độ tinh vi của cấu hình người dùng và các chỉ thị hiện có (đó là lý do tại sao nói chung là một ý tưởng tốt để xem những chỉ thị nào khác mà người dùng có tại chỗ mỗi khi có câu hỏi mod_rewrite).


Cảm ơn liên kết AskApache. Đó là những gì tôi đang tìm kiếm!
sica07

Chú hề AskApache chính thức không được ASF hỗ trợ. Phần lớn những gì ông nói là gây tranh cãi hoặc đơn giản là sai.
thích nghi

@adaptr Vui lòng chia sẻ các tài nguyên ưu việt mà bạn biết rõ.
danlefree

"các tình huống phổ biến trong đó mod_rewrite có vẻ như là công cụ phù hợp cho công việc nhưng không phải vậy?" - chuyển hướng đơn giản , trong đó mod_rewrite chưa được sử dụng. Sử dụng mod_alias Redirecthoặc RedirectMatchthay vào đó. Xem thêm các tài liệu Apache: Khi không sử dụng mod_rewrite
MrWhite

21

Giống như nhiều quản trị viên / nhà phát triển Tôi đã chiến đấu với sự phức tạp của các quy tắc viết lại trong nhiều năm và không hài lòng với tài liệu Apache hiện có, vì vậy tôi đã quyết định làm một dự án cá nhân để tìm hiểu sâu về cách thức mod_rewritethực sự hoạt động và tương tác với phần còn lại của Apache cốt lõi, vì vậy trong vài tháng qua tôi đã sử dụng các trường hợp thử nghiệm với strace+ khoan vào mã nguồn để xử lý tất cả những điều này.

Dưới đây là một số ý kiến ​​chính mà các nhà phát triển quy tắc viết lại cần xem xét:

  • Một số khía cạnh của việc viết lại là phổ biến đối với cấu hình máy chủ, máy chủ ảo, thư mục, xử lý .htaccess tuy nhiên
  • Một số xử lý rất khác nhau đối với cấu hình gốc (cấu hình máy chủ, máy chủ ảo và thư mục) trái ngược với .htaccessxử lý PerDir ( ).
  • Tồi tệ hơn vì quá trình xử lý PerDir gần như có thể kích hoạt chu kỳ GIẢM GIÁ NỘI BỘ, các thành phần cấu hình gốc phải được ghi nhận rằng việc xử lý PerDir như vậy có thể kích hoạt điều này.

Tôi muốn nói rằng vì điều này, bạn gần như cần phải chia cộng đồng người dùng viết lại thành hai loại và coi chúng là hoàn toàn riêng biệt:

  • Những người có quyền truy cập root vào cấu hình Apache . Đây thường là quản trị viên / nhà phát triển với một máy chủ / VM dành riêng cho ứng dụng và thông báo ở đây khá đơn giản: tránh sử dụng .htaccesscác tệp nếu có thể; làm mọi thứ trong máy chủ hoặc cấu hình vhost của bạn. Gỡ lỗi là hợp lý dễ dàng vì nhà phát triển có thể thiết lập gỡ lỗi và có quyền truy cập vào các tệp Rewrite.log.

  • Người dùng của một dịch vụ lưu trữ được chia sẻ (SHS) .

    • Những người dùng như vậy phải sử dụng .htaccess/ xử lý Perdir vì không có sẵn thay thế.
    • Tồi tệ hơn, mức độ kỹ năng của những người dùng như vậy (theo như sử dụng thang logic điều khiển regrec của mod_rewrite) thường ít hơn đáng kể so với các quản trị viên có kinh nghiệm.
    • Apache và các nhà cung cấp dịch vụ lưu trữ không cung cấp hỗ trợ gỡ lỗi / chẩn đoán. Thông tin chẩn đoán duy nhất là chuyển hướng thành công, chuyển hướng đến URI sai. hoặc mã trạng thái 404/500. Điều này khiến họ bối rối và bất lực.
    • Apache cực kỳ yếu giải thích cách viết lại hoạt động cho trường hợp sử dụng này. Ví dụ, nó không cung cấp một lời giải thích rõ ràng về .htaccesstập tin PerDir nào được chọn và tại sao. Nó không giải thích sự phức tạp của việc đạp xe PerDir và cách tránh điều này.

Có thể có một cộng đồng thứ ba: quản trị viên và nhân viên hỗ trợ trong các nhà cung cấp SHS, những người cuối cùng có một chân ở cả hai trại và phải chịu hậu quả của những điều trên.

Tôi đã viết một vài bài đăng trên blog kiểu bài viết (ví dụ: Thêm về cách sử dụng quy tắc Rewrite trong tệp .htaccess ) bao gồm rất nhiều điểm chi tiết mà tôi sẽ không lặp lại ở đây để giữ bài đăng này ngắn. Tôi có dịch vụ chia sẻ của riêng mình cũng như hỗ trợ một số dự án FLOSS chuyên dụng & VM. Tôi đã bắt đầu sử dụng LAMP VM tiêu chuẩn làm phương tiện thử nghiệm cho tài khoản SHS của mình, nhưng cuối cùng tôi thấy tốt hơn khi thực hiện một VM máy nhân bản phù hợp (mô tả ở đây ).

Tuy nhiên, về cách cộng đồng quản trị nên hỗ trợ .htaccessngười dùng, tôi cảm thấy rằng chúng tôi cần phát triển và cung cấp:

  • Một mô tả mạch lạc về cách hệ thống viết lại thực sự hoạt động trong xử lý PerDir
  • Một bộ hướng dẫn / thực tiễn tốt nhất về cách viết .htaccessquy tắc viết lại
  • Một trình phân tích cú pháp viết lại kịch bản lệnh dựa trên web đơn giản tương tự như trình phân tích cú pháp html W3C, nhưng người dùng có thể nhập các URI kiểm tra hoặc các vectơ kiểm tra giống nhau và nhận được một bản ghi ngay lập tức của luồng logic ghi lại /
  • Gợi ý về cách nhận chẩn đoán tích hợp từ quy tắc của bạn (ví dụ:

    • Sử dụng [E=VAR:EXPR]khai thác thực tế EXPRsẽ mở rộng phản hồi ($ N hoặc% N) để làm cho chúng có sẵn dưới dạng chẩn đoán cho tập lệnh đích.
    • Nếu bạn sắp xếp theo thứ tự các quy tắc viết lại của mình bằng cách sử dụng các cờ [OR], [C], [SKIP] và [L] để toàn bộ lược đồ viết lại hoạt động mà không cần khai thác chuyển hướng nội bộ, thì bạn có thể thêm các quy tắc sau như quy tắc 1 để tránh tất cả các rắc rối lặp:

      RewriteCond %{ENV:REDIRECT_STATUS} !=""
      RewriteRule .  -  [L]
      

Đây là tài liệu tốt. Tại sao bạn nói tài liệu không giải thích điều này?
thích nghi

2
Tất cả bạn phải làm là đăng ký các .htaccesschủ đề và bạn sẽ thấy. Hầu hết những người mới bắt đầu đều bối rối vô vọng - hầu hết những người này có trải nghiệm đầu tiên về dịch vụ LAMP và mod_rewrite trên dịch vụ chia sẻ và do đó không có quyền truy cập root vào cấu hình hệ thống / vhost và phải sử dụng cho mỗi xử lý thư mục thông qua .htaccesscác tệp. Có những khác biệt quan trọng mà người mới bắt đầu phải "chảy máu". Tôi sẽ coi mình là một người sử dụng năng lượng và vẫn đang khám phá sự tinh tế. Như tôi đã nói, tôi đã phải sử dụng quét mã vạch và mã nguồn để tìm ra một số khía cạnh. Không cần thiết. :-(
TerryE

Tôi hoàn toàn đồng ý. "Chúng tôi cần chia cộng đồng người dùng viết lại thành hai loại và coi chúng là hoàn toàn riêng biệt." Một số người dùng đang sử dụng lưu trữ chia sẻ và cần phải dựa vào .htaccess, điều này rất mong manh, phức tạp và khó hiểu, ngay cả đối với các chuyên gia. Tôi VẪN gặp rắc rối.
Ryan

15

Sử dụng viết lại

Có rất nhiều điều bạn có thể làm với viết lại. Rewritemaps được khai báo bằng cách sử dụng chỉ thị Rewritemap và sau đó có thể được sử dụng cả trong các đánh giá RewritCond và trong các phần đăng ký RewriteRule.

Cú pháp chung cho RewriteMap là:

RewriteMap MapName MapType:MapSource

Ví dụ:

RewriteMap examplemap txt:/path/to/file/map.txt

Sau đó, bạn có thể sử dụng tên bản đồ cho các cấu trúc như thế này:

${examplemap:key}

Bản đồ chứa các cặp khóa / giá trị. Nếu khóa được tìm thấy, giá trị được trợ cấp. Bản đồ đơn giản chỉ là các tệp văn bản đơn giản, nhưng bạn có thể sử dụng bản đồ băm và thậm chí các truy vấn SQL. Thông tin chi tiết có trong tài liệu:

http://httpd.apache.org/docs/2.2/mod/mod_rewrite.html#rewritemap

Chuỗi không định hình.

Có bốn bản đồ nội bộ bạn có thể sử dụng để thực hiện một số thao tác. Đặc biệt là chuỗi unescaping có thể có ích.

Ví dụ: Tôi muốn kiểm tra chuỗi "café" trong chuỗi truy vấn. Tuy nhiên, trình duyệt sẽ thoát khỏi điều này trước khi gửi nó đến máy chủ của tôi, vì vậy tôi cần tìm ra phiên bản thoát URL nào cho mỗi chuỗi tôi muốn khớp hoặc tôi chỉ có thể bỏ qua nó ...

RewriteMap unescape int:unescape

RewriteCond %{QUERY_STRING}  (location|place)=(.*)
RewriteCond ${unescape:%2}   café
RewriteRule ^/find/$         /find/1234? [L,R]

Lưu ý cách tôi sử dụng một RewriteCond để chỉ nắm bắt đối số tham số chuỗi truy vấn, sau đó sử dụng bản đồ trong lần ghi lại thứ hai để hủy bỏ nó. Điều này sau đó được so sánh. Cũng lưu ý cách tôi cần cho chúng tôi% 2 làm khóa trong bản ghi lại, vì% 1 sẽ chứa "vị trí" hoặc "địa điểm". Khi bạn sử dụng dấu ngoặc đơn để nhóm các mẫu, chúng cũng sẽ bị bắt, khi đó bạn có kế hoạch sử dụng kết quả của việc chụp hay không ...


Câu cuối cùng không hoàn toàn đúng. Công mod_rewritecụ regrec hỗ trợ các nhóm không bắt giữ như (?:location|place)và điều này sẽ chỉ có một lần chụp trong ví dụ.
TerryE

12

Những sai lầm / cạm bẫy phổ biến nhất khi viết quy tắc viết lại là gì?

Một cạm bẫy thực sự dễ dàng là khi bạn viết lại các URL thay đổi đường dẫn rõ ràng, ví dụ từ /base/1234/index.htmlđến /base/script.php?id=1234. Bất kỳ hình ảnh hoặc CSS nào có đường dẫn tương đối đến vị trí tập lệnh sẽ không được tìm thấy bởi máy khách. Một số tùy chọn để giải quyết điều này có thể được tìm thấy trên faq này .


1
Cảm ơn các liên kết. Đặc biệt, khi làm việc với các thành viên khác trong nhóm không quen với việc viết lại, tôi thấy việc thêm một <base>thẻ để dễ theo dõi nhất và vẫn cho phép các đường dẫn tương đối.
kontur
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.