在第一次測試中,我們沒有設定任何 URL 參數串,是以輸出 <code>$orig_args</code> 變量的值時便得到空。而在第一次和第二次測試中,無論我們是否提供 URL 參數串,參數串都會在 <code>location /test</code> 中被強行改寫成 <code>a=3&b=4</code>.
我們來實際通路一下第一個虛拟主機的 <code>/test</code> 接口:
在讀取變量時執行的這段特殊代碼,在 Nginx 中被稱為“取處理程式”(get handler);而改寫變量時執行的這段特殊代碼,則被稱為“存處理程式”(set handler)。不同的 Nginx 子產品一般會為它們的變量準備不同的“存取處理程式”,進而讓這些變量的行為充滿魔法。
其實這種技巧在計算世界并不鮮見。比如在面向對象程式設計中,類的設計者一般不會把類的成員變量直接暴露給類的使用者,而是另行提供兩個方法(method),分别用于該成員變量的讀操作和寫操作,這兩個方法常常被稱為“存取器”(accessor)。下面是 C++ 語言中的一個例子:
在這個名叫 <code>Person</code> 的 C++ 類中,我們提供了 <code>get_name</code> 和 <code>set_name</code> 這兩個公共方法,以作為私有成員變量<code>m_name</code> 的“存取器”。
這樣設計的好處是顯而易見的。類的設計者可以在“存取器”中執行任意代碼,以實作所需的業務邏輯以及“副作用”,比如自動更新與目前成員變量存在依賴關系的其他成員變量,抑或是直接修改某個與目前對象相關聯的資料庫表中的對應字段。而對于後一種情況,也許“存取器”所對應的成員變量壓根就不存在,或者即使存在,也頂多扮演着資料緩存的角色,以緩解被代理資料庫的通路壓力。
與面向對象程式設計中的“存取器”概念相對應,Nginx 變量也是支援綁定“存取處理程式”的。Nginx 子產品在建立變量時,可以選擇是否為變量配置設定存放值的容器,以及是否自己提供與讀寫操作相對應的“存取處理程式”。
不是所有的 Nginx 變量都擁有存放值的容器。擁有值容器的變量在 Nginx 核心中被稱為“被索引的”(indexed);反之,則被稱為“未索引的”(non-indexed)。
(未完待續)