NGINX 的核心架構採用模組化設計,允許開發者根據需求選擇和組態不同的模組。這使得 NGINX 非常靈活,可以適應各種不同的應用場景。文章首先介紹了 NGINX 模組的分類別,包括預設啟用、編譯時啟用以及第三方模組。接著,重點探討了 Rewrite 模組的功能,說明如何利用正規表示式進行 URL 重寫,以及如何藉此提升網站的 SEO 和使用者經驗。更進一步地,文章詳細解釋了正規表示式的基本語法,包含各種元字元、數量詞以及捕捉群組的用法,並輔以實際案例說明如何在 NGINX 組態中有效運用這些技巧。最後,文章還區分了 NGINX 處理外部請求和內部請求的差異,並提供相關指令和組態範例,讓讀者更全面地理解 NGINX 的運作方式。
模組組態探索:NGINX的核心功能
NGINX的真正強大之處在於其模組系統。整個應用程式都是建立在模組化架構上,每個模組都可以在編譯時啟用或停用。有些模組提供簡單的功能,例如 autoindex 模組,它可以生成目錄中的檔案列表。而有些模組則會完全改變你對網頁伺服器的認知,例如 Rewrite 模組。除了現有的 NGINX 模組外,開發者還可以根據需要建立自己的模組。
在本章末尾,你可以找到第三方模組系統的快速概述。請注意,第三方模組由社群維護,並不保證這些模組會與你的 NGINX 版本相容。
本章涵蓋以下主題:
Rewrite模組:不僅僅是重寫 URI- 預設 NGINX 版本中啟用的其他模組
- 必須在編譯時啟用的可選模組
- 第三方模組的簡要說明
深入探索 Rewrite 模組
Rewrite 模組為 NGINX 帶來了遠超過簡單指令集的功能。它定義了一個全新的請求處理層級,這一部分將在接下來的內容中詳細說明。
首先,這個模組(如名稱所暗示)用於進行 URL 重寫。這個機制允許你去除包含多個引數的醜陋 URL,例如 http://example.com/article.php?id=1234&comment=32。這些 URL 對一般訪客來說特別不具資訊量且無意義。
相反地,連結到你網站的 URL 將包含有用的資訊,指示即將存取的頁面性質。例如,URL http://website.com/article-1234-32-US-economy-strengthens.html 不僅對訪客更有趣,對搜尋引擎也更友好。URL 重寫是搜尋引擎最佳化(SEO)的關鍵元素。
這個機制的原理非常簡單:它是在接收到客戶請求後、提供檔案前重寫請求 URI。重寫後,URI 會與位置區塊進行比對,以找到應用於請求的組態。這項技術將在後續部分中詳細說明。
正規表示式回顧
首先,這個模組需要一定程度上的正規表示式(regex 或 regexp)理解。因為 URL 重寫是透過 rewrite 指令完成的,該指令接受一個模式後跟隨替換 URI。
這是一個廣泛的話題;有整本文專門解釋其奧妙。然而,我們即將檢視的簡化方法應該足夠讓你充分利用這個機制。
正規表示式的目的
我們首先要回答的問題是:正規表示式的目的是什麼?簡單來說,其主要目的是驗證一個字串是否比對給定模式。該模式使用特定語言來定義極其複雜且精確的規則:
| 字串 | 模式 | 是否比對 | 說明 |
|---|---|---|---|
| hello | ^hello$ | 是 | 字串從 h 開始(^h),接著是 e, l, l ,然後以 o 結束(o$)。 |
| hell | ^hello$ | 否 | 字串從 h 開始(^h),接著是 e, l, l ,但不以 o 結束。 |
| Hello | ^hello$ | 未知 | 若執行比對的是區分大小寫引擎,則字串不比對該模式 |
表格4.1:包含說明的一些模式
當使用更複雜的模式時,這一概念變得更加有趣。例如:驗證電子郵件地址: ^[A-Z0-9._%+-]+@[A-Z0-9.-]+.[A-Z]{2,4}$。程式化驗證一個合法電子郵件地址可能需要大量程式碼,而所有工作都可以透過單一正規表示式進行。
PCRE 語法
NGINX 使用的是 Perl Compatible Regular Expressions (PCRE) 函式庫語法(如果記得第2章),這對於自行構建 NGINX 是必需的一項前提條件,除非你停用使用它們的模組。它是最常見的一種正規表示式形式,幾乎所有你學到的是都適用於其他語言變體。
在最簡單形式下,一個模式由一個字元構成——例如 x。我們可以將字串與該模式進行比對。“example” 比對 x 模式嗎?是的,“example” 包含字元 “x”。它還可以是多個特定字元;[a-z] 模式比對 a 和 z 之間任意一個字元, 或甚至是字母和數字的混合: [a-z0-9]。因此, “hell[a-z0-9]” 模式驗證以下字串: “hello” 和 “hell4”,但不包括 “hell” 或 “hell!"。
你可能已經注意到我們使用了 [ 和 ] 段落符號,它們被稱為元字元, 對於讓語法更具指導性起著重要作用。總共有11種元字元,每個都扮演著不同角色。 若要建立實際包含其中之一元字元,必須逃避該段落 (\反斜槓):
| 元字元 | 說明 |
|---|---|
| ^ | 開始 此字元後面必須是開頭: • 範例段落: ^h • 比對範例: hello, h, hh (任何以 h 開始) • 不比對範例: character, ssh |
| $ | 結果 此字元前面必須位於結尾: • 範例段落: e$ • 比對範例: sample, e, file (任何以 e結尾) • 不比對範例: extra, shell |
| . (點) | 任意 比對任何字元: • 範例段落: hell. • 比對範例: hello, hellx, hell5 和 hell! • 不比對範例: hell 和 helo |
自行建立最適合需求之自定義 Rewrite 條件
玄貓認為解析清楚 Rewrite 的內容後就可以輕鬆地使用其指令進行適當調整。 Rewrite 條件可以根據 URL、HTTP Header、變數等多種條件進行判斷。 以下是幾個常見條件及其應用情境:
# 根據 URL 的條件
rewrite ^/old-path/(.*) /new-path/$1 break;
# 根據 HTTP Header 的條件
if ($http_user_agent ~* MSIE) {
rewrite ^(.*)$ /ie/$1 break;
}
# 根據變數值判斷
set $my_var "value";
if ($my_var = "value") {
rewrite ^(.*)$ /custom/$1 break;
}
內容解密:
上述程式碼展示瞭如何根據不同條件進行重寫操作。
- 第一段程式碼中,NGINX 檢查請求 URL 是否以
/old-path/開始。 如果比對成功則會將/old-path/則替換為/new-path/。 - 第二段程式碼中檢查 HTTP Header 中 User-Agent 是否包含 MSIE。
如果比對成功則將所有請求轉向
/ie/下。 - 第三段程式碼中會先設定變數
$my_var的值為 value。 然後再檢查$my_var是否等於 value。 如果條件成立則轉向/custom/下。
玄貓認為只要稍微瞭解一下 Rewrite 指令和常見條件, 就能根據實際需求構建出最適合自己的 Rewrite 組態。 以上示範了幾種常見情境及其應對策略, 希望能夠幫助大家更好地掌握 Rewrite 的使用技巧, 進而提升網站管理和最佳化能力。
Mermaid
graph TD;
A[客戶端請求] --> B{URL 比對};
B -- 比對成功 --> C[URI 轉向];
B -- 比對失敗 --> D[直接處理];
C --> E[位置區塊];
D --> E;
內容解密:
此圖示展示了 NGINX 在處理客戶端請求時如何透過 URI 轉向來決定應用哪些位置區塊。當客戶端發出請求時(A),NGINX 首先檢查 URL 是否與重寫規則比對(B)。如果比對成功(C),URI 會被轉向到新位置;如果未比對(D),則直接處理原始請求並應用相應位置區塊(E)。
NGINX 的 Rewrite 模組提供了靈活且強大的功能來處理和轉發 HTTP 請求。透過理解和掌握這些功能,我們可以實作更高效和可靠的網站伺服器管理和最佳化。玄貓希望透過深入瞭解和實踐 NGINX 的 Rewrite 模組功能來提升網站效能和使用者經驗。
NGINX 正規表示式與重寫模組深度探索
NGINX 是一個強大的網頁伺服器,其功能強大且靈活,特別是在處理 URL 重寫和正規表示式時。本文將探討 NGINX 中的正規表示式及其在重寫模組中的應用,並提供實際案例和詳細解說。
正規表示式元字元
正規表示式是一種強大的工具,能夠用來比對和操作文字。以下是一些常見的元字元及其在 NGINX 中的應用:
[ ]:字元集
- 說明:比對指定集合中的任何字元。
- 語法:
[a-z]表示比對任何小寫字母,[abcd]表示比對a、b、c或d,[a-z0-9]表示比對任何小寫字母或數字。 - 範例模式:
hell[a-y123-]。 - 比對字串:
hello、hell1、hell2、hell3、hell-。 - 不比對字串:
hellz、hell4、heloo、he-llo。
[^ ]:否定字元集
- 說明:比對不在指定集合中的任何字元。
- 語法:
[^a-np-z0-9]。 - 比對字串:
hello、hell!。 - 不比對字串:
hella、hell5。
|:替代
- 說明:比對
|前後的任一模式。 - 語法:
hello|welcome。 - 比對字串:
hello、welcome、helloes、awelcome。 - 不比對字串:
helloelloeslo,ellow,owelcom.
- 說明:比對
( ):分組
- 說明:將多個模式分組,通常用於替代或捕捉。
- 語法:
^(hello|hi) there$ - 比對字串:
'hello there'或'hi there' - 不比對字串:
'hey there'或'ahoy there'
\:轉義
- 說明:用於轉義特殊字元,使其成為普通字元。
- 語法:
'Hello\\' - 比對字串:
'Hello.'不比對字串: ‘Hello’, ‘Hello!how are you?’
數量詞
數量詞允許您擴充套件接受的實體數量。以下是一些常見的數量詞及其應用:
*:0 次或多次
- 說明: 前面的實體可以出現0次或多次
模式: he*llo 比對: hllo, hello, heeeello 不比對: hallo, ello+:1 次或多次
模式: he+llo 比對: hello, heeeello 不比對: hllo, helo?****:0 次或1次
模式: he?llo 比對: hello, hllo 不比對: heello, heeeello{x}:x 次
模式: he{3}llo 比對: heeello, oh heeello there! 不比對: hello, heello, heeeello{x,}:至少 x 次
模式: he{3,}llo 比對: heeello, heeeeeeello 不比對: hllo, hello, hello{x,y}:x到y次**
模式: he{2,4}llo 比對: heello, heeello, heeeello. 不比對: hello, heeeeello.
由於 NGINX 組態檔案語法中的大括號會與正規表示式中的大括號衝突,因此需要將包含大括號的模式放在引號中:
rewrite hel{2,}o /hello.php; # 無效的寫法
rewrite "hel{2,}o" /hello.php; # 有效的寫法
rewrite 'hel{2,}o' /hello.php; # 有效的寫法
捕捉群組
捕捉群組是正規表示式的一個強大功能,允許您捕捉子表示式並將其儲存在變數中。這些變數可以在後續指令中使用。
例如:
模式: ^(hello|hi) (sir|mister)$
比對字串: 'hello sir'
捕捉結果:
$1 = hello,
$2 = sir.
模式 : ^(.*)$
比對字串:'nginx rocks'
捕捉結果:
$1=nginx rocks.
捕捉命名
NGINX 支援使用命名捕捉來提高可讀性。例如:
模式 : ^/(?<folder>[^/]+)/(?<file>.*)$
url : '/admin/doc'
捕捉結果:
$folder = admin,
$file = doc.
在 NGINX 中應用正規表示式
在 NGINX 中,您可以在 location 塊中使用正規表示式來比對請求 URI。例如:
server {
server_name website.com;
location ~* ^/(downloads|files)/(.*)$ {
add_header Capture1 $1;
add_header Capture2 $2;
}
}
在這個例子中,當請求 URI 與正規表示式 /downloads/file.txt, /files/archive.zip, 或 /files/docs/report.doc.時會被捕捉到:
$1 = downloads or files,
$2 = file.txt or archive.zip or report.doc.
外部與內部請求
NGINX 做出了外部請求與內部請求之間的區別。外部請求直接來自客戶端並被比對可能的 location 塊。
server {
server_name website.com;
location = /document.html {
deny all; # 測試指令.
}
}
#這樣一來當客戶端請求 http://website.com/document.html.時就會被拒絕連線.
內部請求由 NGINX 本身觸發,並且需要具備特定的指令才能產生。例如:
error_page, index, rewrite, try_files,
add_before_body and add_after_body (from the addition module)
Server-Side Includes (SSI) command.
