Hướng dẫn viết lại URL với mod_rewrite cho Apache trên Ubuntu 16.04

6 năm trước

Lời mở đầu

Trong hướng dẫn này, chúng ta sẽ học cách dùng module mod_rewrite  của Apache. Module này cho phép chúng ta viết lại URL gọn hơn, dịch các đường dẫn mà con người có thể đọc được sang chuỗi câu hỏi có lợi cho code hoặc điều hướng lại các URL dựa trên các điều kiện bổ sung.
Hướng dẫn này được chia là 2 phần. Phần 1 sẽ tạo một website mẫu và thực hiện viết lại mẫu đơn giản. Phần thứ 2 sẽ bao gồn 2 ví dụ sâu hơn về các quy tắc viết lại thông dụng.

Điều kiện cần

Để làm theo các bước hướng dẫn này bạn sẽ cần:

 

Bước 1 — Enabling mod_rewrite

Đầu tiên chúng ta cần kích hoạt mod_rewrite.Nó tuy có sẵn nhưng chưa được kích hoạt cho dù đã cài đặt Apache 2

sudo a2enmod rewrite

 Câu lệnh này sẽ kích hoạt module hoặc thông báo cho bạn module đã được bật. Để lưu những thay đổi này, khởi động lại Apache

sudo systemctl restart apache2

mod_rewrite đã được kích hoạt. Trong bước tiếp theo bạn sẽ tạo file .htaccess sử dụng xác định quy tắc viết lại cho việc chuyển hướng.

 

Bước 2 — Setting Up .htaccess

File .htaccess cho phép chúng t thay đổi các quy tắc viết lại mà không cần truy cập vào file cấu hình server. Vì lí do này mà .htaccess cực kì quan trọng với bảo mật ứng dụng web. Chu kì đứng trước tên file sẽ chắc chắn rằng file này sẽ bị ẩn đi.

Note: Bất kì quy luật mà bạn đặt trong file .htaccess có thể đặt trực tiếp trong file cấu hình server. Thực tế thì các tài liệu chính thức của Apache khuyên dùng sử dung file cấu hình server thay vì.htaccess vì Apache sẽ xử lí no nhanh hơnTuy nhiên trong ví dụ đơn giản này, hiệu quả sẽ là không đáng kể. Thêm vào đó việc đặt các quy tắc trong .htaccessrất bất tiện, đặc biệt với nhiều website trên cùng một server.  Nó không yêu cầu khởi động lại server để lưu những thay đổi và cũng không cần quyền root để thay đổi quy luật đó, nó đơn giản hoá bảo trì và làm cho những thay đổi đó hoạt động được với những tài khoản không được cấp phép.Một số  software nguồn mở như Wordpress và Joomla thường dựa trên file .htaccess để thay đổi software và tạo ra thêm nhưng quy tắc nếu yêu cầu.

 

Bạn sẽ cần cài đặt và bảo mật một vài thứ trước khi chúng ta bắt đầu.

Apache mặc định cấm sử dụng file .htaccess để áp dụng các quy tắc mới, cho nên đầu tiên bạn cần cho phép thay đổi trên file đó. Mở cấu hình Apache mặc đijnh bằng cách sử dụng nano hoặc trình chỉnh sửa văn bản yêu thích của bạn

sudo nano /etc/apache2/sites-available/000-default.conf

Bên trong file bạn sẽ thấy khối  bắt đầu ngay ở dòng đầu. Bên trong khối đó, thêm một khối mới để file cấu hình như bên dưới. Chắc chắn rằng tất cả các khối đều được thụt lề đúng cách

/etc/apache2/sites-available/000-default.conf
Options Indexes FollowSymLinks MultiViewsAllowOverride AllRequire all granted 
. . .

Lưu và đóng file lại. Khởi động Apache để lưu những thay đổi.

sudo systemctl restart apache2

Tạo file.htaccess trong root web.

sudo nano /var/www/html/.htaccess

Thêm dòng này vào đầu file mới để bật engine viết lại.

/var/www/html/.htaccess
RewriteEngine on

Lưu file và thoát.

Bạn đã có file .htaccess hoạt động dùng để thay đổi quy tắc định tuyến của ứng dụng web. Trong bước tiếp theo, chúng ta sẽ tạo một website mẫu dùng để xác định quy tắc viết lại.

 

Bước 3 — Configuring URL Rewrites

Chúng ta sẽ viết lại URL cơ bản về thay đổi các dòng URL ổn thành đường dẫn code thật. Cụ thể, bạn sẽ cho phép người dùng truy cập vào http://your_server_ip/about.

Bắt đầu với tạo file rồi đặt tên là about.html trong root web.

sudo nano /var/www/html/about.html

Copy code HTML này vào trong file, sau đó lưu và đóng nó.

/var/www/html/about.html
 About Us

Bạn có thể truy cập trang tại địa chỉ http://your_server_ip/about.html, nhưng lưu ý rằng nếu bạn vẫn cố gắng truy cập http://your_server_ip/about , bạn sẽ thấy lỗi 404 Not Found . Nếu bạn truy cập trang bằng cách dùng about thay thế, quy luật viết lại sẽ hoạt động.

Tất cả RewriteRules đều tuân theo format dưới đây:

General RewriteRule structure
RewriteRule pattern substitution [flags]
  • RewriteRule chỉ rõ chỉ thị.
  • pattern  là biểu thức khớp với chuỗi mong muốn từ URL và là kiểu người xem trong trình duyệt
  • substitution là đường dẫn tới URL thật, ví dụ như đường dẫn tới file server Apache.
  • flags  là tham số tuỳ chọn có thể thay đổi cách quy tắc hoạt động.

Mở file.htaccess.

sudo nano /var/www/html/.htaccess

Sau dòng đầu tiên, thêm RewriteRule được đánh dấu đỏ và lưu file lại

/var/www/html/.htaccess
RewriteEngine onRewriteRule ^about$ about.html [NC]

Trong trường hợp này, ^about$ là pattern, about.html là  substitution và [NC] là flag. Ví dụ của chúng ta sử dụng một vài dấu chữ với ý nghĩa đặc biệt:

  • chi biết nơi bắt đầu của URL, sau your_server_ip/.
  • $ chỉ ra kết thúc của URL..
  • about nối với chuỗi  "about".
  • about.html là file thực tại mà người dùng đang truy cập.
  • [NC] là flag làm cho các quy tắc không chính xác.

Bây giờ bạn có thể truy cập vào http://your_server_ip/about trong trình duyệt của mình.Trên thực tế, với quy tắc nói bên trên, những URL sau sẽ nhắm tới about.html:

  • http://your_server_ip/about, bởi vì định nghĩa quy luật
  • http://your_server_ip/About, bởi vì quy luật không chính xác.
  • http://your_server_ip/about.html bởi vì tên hợp lệ ban đầu của file luôn luôn hoạt động.

Những dòng sau đây sẽ không :

  • http://your_server_ip/about/,  bởi vì quy tắc rõ ràng nêu rằng không có gì sau about bằng cách dùng dấu chữ $
  • http://your_server_ip/contact,  vì nó không khớp với chuỗi about trong quy luật.

 

Bây giờ bạn đã có một file .htaccess có thể hoạt động cới quy tắc đơn giản mà bạn có thể thay đổi và mở rộng nhu cầu của mình. Trong phần tiếp theo, chúng tôi sẽ chỉ thêm hai ví dụ của các chỉ thị thường được sử dụng.

 

Ví dụ 1 — Simplifying Query Strings with RewriteRule

Ứng dụng web thường dùng chuỗi câu hỏi được nối vào một URL sử dụng dấu (?) sau địa chỉ. Các tham số riêng được phân cách bằng dấu (&) . Chuỗi câu hỏi có thể dùng để chuyển dữ liệu thêm vào giữa các trang ứng dụng độc lập.

Ví dụ, một trang tìm kiếm kết quả được viết bằng ngôn ngữ lập trình PHP có thể dùng URL kiểu như http://example.com/results.php?item=shirt&season=summer .Ở trong ví dụ này. 2 tham số thêm vào được chuyển tới kết quả result.php ảo, application script:item , với giá trị shirt ,và season với giá trị summer. Ứng dụng có thể dùng thông tin chuỗi câu hỏi để tạo lên page đúng cho người truy cập.

Apache rewrite rules thường được dùng để đơn giản hoá những đường linh dài dòng và khó chịu như bên trên thành những friendly URL dễ gõ hơn và dễ hiểu khi nhìn vào.Trong ví dụ này, chúng ta sẽ đi đơn giản hoá dòng link này http://example.com/shirt/summer. Gía trị tham số shirt và summer vẫn ở trong địa chỉ nhưng không ở trong chuỗi câu hỏi và tên script.

Đây là một quy tắc để thực hiện điều này:

Simple substition
RewriteRule ^shirt/summer$ results.php?item=shirt&season=summer [QSA]

shirt/summer is rõ ràng khớp trong địa chỉ yêu cầu và Apache được yêu cầu xử lí results.php?item=shirt&season=summer thay vào đó.

Flag [QSA] được sử dụng rộng rãi trong viết lại quy luật. Chúng yêu cầu Apache kết nối thêm bất kì chuỗi câu hỏi nào tới URL đang được xử lí, cho nên nếu người truy cập gõ http://example.com/shirt/summer?page=2 thì server phản hồi vớiresults.php?item=shirt&season=summer&page=2. Không có phản hồi đó tức là chuỗi câu hỏi đã bị loại bỏ.

Trong khi phương pháp này đạt được những kết quả mong muốn, cả item name và season được mã hoá cứng thành quy tắc. Tức là có nghĩa là quy tắc này sẽ không hoại động với bất kì item nào như  pants hay bất cứ season nào nhưwinter.

Để làm cho những quy tắc chung chung hơn, chúng ta có thể dùng biểu thức chính quy để nối những phần của địa chỉ ban đầu và dùng phần đó trong substitution pattern. Quy luật sau khi được thay đổi sẽ như sau:

Simple substition
RewriteRule ^([A-Za-z0-9]+)/(summer|winter|fall|spring) results.php?item=$1&season=$2 [QSA]

Nhóm biểu thức chính quy đầu tiên trong dấu ngoặc đơn khớp với chuỗi chứa các  dấu chữ và số như shirt hoặc pants và lưu phần được nối là biến $1. Nhóm biểu thức chính quy thức hai trong dấu ngoặc đơn khớp chính xác summerwinterfall, hoặc spring, và đơn giản lưu phần được nốilà $2.

Phần đã được nối sau đó được dùng trong việc tìm ra kết quả URL trong biến item và season thay vì giá trị được mã hoá cứng shirt và summer mà ta sử dụng trước đó.

Ví dụ như những thứ bên trên sẽ chuyển đổi từ http://example.com/pants/summer thành http://example.com/results.php?item=pants&season=summer. Ví dụ đó cũng là một future proof, cho phép nhiều item và season được viết lại bằng một quy tắc.

Ví dụ 2 — Adding Conditions with Logic Using RewriteConds

Các quy tắc viết lại không nhất thiết phải luôn luôn được đánh giá từng cái một mà không có bất kì hạn chế nào. Chỉ thị RewriteCond cho phép chúng ta bổ sung các điều kiện để kiểm soát quy tắc viết lại của chúng ta khi chúng đang được tiến hành. Tất cả RewriteConds tuân theo format dưới đây:

General RewriteCond structure
RewriteCond TestString Condition [Flags]
  • RewriteCond chỉ rõ chỉ thị RewriteCond .
  • TestString is là chuỗi để test lên.
  • Condition là pattern hoặc điều kiện để nối.
  • Flags là tham số tuỳ chọn có thể thay đổi điều kiện và các quy tắc đánh giá.

Nếu RewriteCond đánh giá đúng thì tiếp đến RewriteRule sẽ được đánh giá. Nếu không, quy tắc này sẽ bị loại. Nhiều RewriteCond có thể được dùng sau cái khác với hành vi mặc định, tất cả phải được đánh giá đúng thì các quy tắc sau mới được đánh giá

Ví dụ hay coi như chúng ta muốn chuyển hướng tất cả request đến một file hoặc thư mục không tồn tại về trang chủ thay vì hiển thị 404 Not Found. Đó có thể làm đươc với dòng quy tắc sau:

Redirect all requests to non-existent files and directories to home page
RewriteCond %{REQUEST_FILENAME}!-f
RewriteCond %{REQUEST_FILENAME}!-d
RewriteRule . /

Với những điều trên:

  • %{REQUEST_FILENAME} là chuỗi để check.Trong trường hợp này thì nó là tên file được yêu cầu mà hệ thống biến khả dụng cho mọi request.
  • -f à điều kiện được xây dựng để xác minh liệu rằng tên được yêu cầu có tồn tại trên đĩa hoặc file không. ! là toán tử phủ định. Khi được kết hợp, !-f đánh giá đúng chỉ khi tên cụ thể không hề tồn tại hoặc không là một file.
  • !-d đơn giản đánh giá đúng chỉ khi tên cụ thể không tồn tại hoặc không phải là một tệp

RewriteRule ở dòng cuối cùng sẽ có hiệu lực chỉ với những request tới file hoặc thư mục không tồn tại. The RewriteRule bản thân nó rất đơn giản và chuyển hướng mọi request tới root website /.

Kết luận

mod_rewrite là một module Apache rất hữu ích dùng để đảm bảo con người có thể đọc được các URL.Trong bài hướng dẫn này, bạn đã học cách sử dụng chỉ thị RewriteRule để chuyển hướng các URL, bao gồm các chuỗi câu hỏi. Bạn cũng đã học được cách chuyển hướng URL mọt cách có điều kiện bằng cách sử dụng chỉ thị RewriteCond.