也有一些內(nèi)建變量是支持改寫的,其中一個例子是 $args. 這個變量在讀取時返回當(dāng)前請求的 URL 參數(shù)串(即請求 URL 中問號后面的部分,如果有的話 ),而在賦值時可以直接修改參數(shù)串。我們來看一個例子:
召陵網(wǎng)站建設(shè)公司創(chuàng)新互聯(lián)建站,召陵網(wǎng)站設(shè)計制作,有大型網(wǎng)站制作公司豐富經(jīng)驗。已為召陵成百上千提供企業(yè)網(wǎng)站建設(shè)服務(wù)。企業(yè)網(wǎng)站搭建\外貿(mào)網(wǎng)站制作要多少錢,請找那個售后服務(wù)好的召陵做網(wǎng)站的公司定做!location /test { set $orig_args $args; set $args "a=3&b=4"; echo "original args: $orig_args"; echo "args: $args"; } 這里我們把原始的 URL 參數(shù)串先保存在 $orig_args 變量中,然后通過改寫 $args 變量來修改當(dāng)前的 URL 參數(shù)串,最后我們用 echo 指令分別輸出 $orig_args 和 $args 變量的值。接下來我們這樣來測試這個 /test 接口:
$ curl \'http://localhost:8080/test\' original args: args: a=3&b=4 $ curl \'http://localhost:8080/test?a=0&b=1&c=2\' original args: a=0&b=1&c=2 args: a=3&b=4 在第一次測試中,我們沒有設(shè)置任何 URL 參數(shù)串,所以輸出 $orig_args 變量的值時便得到空。而在第一次和第二次測試中,無論我們是否提供 URL 參數(shù)串,參數(shù)串都會在 location /test 中被強(qiáng)行改寫成 a=3&b=4. 需要特別指出的是,這里的 $args 變量和 $arg_XXX 一樣,也不再使用屬于自己的存放值的容器。當(dāng)我們讀取 $args 時,Nginx 會執(zhí)行一小段代碼,從 Nginx 核心中專門存放當(dāng)前 URL 參數(shù)串的位置去讀取數(shù)據(jù);而當(dāng)我們改寫 $args 時,Nginx 會執(zhí)行另一小段代碼,對相同位置進(jìn)行改寫。Nginx 的其他部分在需要當(dāng)前 URL 參數(shù)串的時候,都會從那個位置去讀數(shù)據(jù),所以我們對 $args 的修改會影響到所有部分的功能。我們來看一個例子:
location /test { set $orig_a $arg_a; set $args "a=5"; echo "original a: $orig_a"; echo "a: $arg_a"; } 這里我們先把內(nèi)建變量 $arg_a 的值,即原始請求的 URL 參數(shù) a 的值,保存在用戶變量 $orig_a 中,然后通過對內(nèi)建變量 $args 進(jìn)行賦值,把當(dāng)前請求的參數(shù)串改寫為 a=5 ,最后再用 echo 指令分別輸出 $orig_a 和 $arg_a 變量的值。因為對內(nèi)建變量 $args 的修改會直接導(dǎo)致當(dāng)前請求的 URL 參數(shù)串發(fā)生變化,因此內(nèi)建變量 $arg_XXX 自然也會隨之變化。測試的結(jié)果證實了這一點:
$ curl \'http://localhost:8080/test?a=3\' original a: 3 a: 5 我們看到,因為原始請求的 URL 參數(shù)串是 a=3, 所以 $arg_a 最初的值為 3, 但隨后通過改寫 $args 變量,將 URL 參數(shù)串又強(qiáng)行修改為 a=5, 所以最終 $arg_a 的值又自動變?yōu)榱?5. 我們再來看一個通過修改 $args 變量影響標(biāo)準(zhǔn)的 HTTP 代理模塊 ngx_proxy 的例子:
server { listen 8080; location /test { set $args "foo=1&bar=2"; proxy_pass http://127.0.0.1:8081/args; } } server { listen 8081; location /args { echo "args: $args"; } } 這里我們在 http 配置塊中定義了兩個虛擬主機(jī)。第一個虛擬主機(jī)監(jiān)聽 8080 端口,其 /test 接口自己通過改寫 $args 變量,將當(dāng)前請求的 URL 參數(shù)串無條件地修改為 foo=1&bar=2. 然后 /test 接口再通過 ngx_proxy 模塊的 proxy_pass 指令配置了一個反向代理,指向本機(jī)的 8081 端口上的 HTTP 服務(wù) /args. 默認(rèn)情況下,ngx_proxy 模塊在轉(zhuǎn)發(fā) HTTP 請求到遠(yuǎn)方 HTTP 服務(wù)的時候,會自動把當(dāng)前請求的 URL 參數(shù)串也轉(zhuǎn)發(fā)到遠(yuǎn)方。 而本機(jī)的 8081 端口上的 HTTP 服務(wù)正是由我們定義的第二個虛擬主機(jī)來提供的。我們在第二個虛擬主機(jī)的 location /args 中利用 echo 指令輸出當(dāng)前請求的 URL 參數(shù)串,以檢查 /test 接口通過 ngx_proxy 模塊實際轉(zhuǎn)發(fā)過來的 URL 請求參數(shù)串。 我們來實際訪問一下第一個虛擬主機(jī)的 /test 接口:
$ curl \'http://localhost:8080/test?blah=7\' args: foo=1&bar=2 我們看到,雖然請求自己提供了 URL 參數(shù)串 blah=7,但在 location /test 中,參數(shù)串被強(qiáng)行改寫成了 foo=1&bar=2. 接著經(jīng)由 proxy_pass 指令將我們被改寫掉的參數(shù)串轉(zhuǎn)發(fā)給了第二個虛擬主機(jī)上配置的 /args 接口,然后再把 /args 接口的 URL 參數(shù)串輸出。事實證明,我們對 $args 變量的賦值操作,也成功影響到了 ngx_proxy 模塊的行為。 在讀取變量時執(zhí)行的這段特殊代碼,在 Nginx 中被稱為“取處理程序”(get handler);而改寫變量時執(zhí)行的這段特殊代碼,則被稱為“存處理程序”(set handler)。不同的 Nginx 模塊一般會為它們的變量準(zhǔn)備不同的“存取處理程序”,從而讓這些變量的行為充滿魔法。 其實這種技巧在計算世界并不鮮見。比如在面向?qū)ο缶幊讨校惖脑O(shè)計者一般不會把類的成員變量直接暴露給類的用戶,而是另行提供兩個方法(method),分別用于該成員變量的讀操作和寫操作,這兩個方法常常被稱為“存取器”(accessor)。下面是 C++ 語言中的一個例子:
#include