Nginx 內置綁定變量的介紹

使用 Nginx 內置綁定變量

Nginx作爲一個成熟、久經考驗的負載均衡軟件,與其提供豐富、完整的內置變量是分不開的,它極大增加了對Nginx網絡行爲的控制細度。這些變量大部分都是在請求進入時解析的,並把他們緩存到請求cycle中,方便下一次獲取使用。首先來看看Nginx對都開放了那些API

參看下錶:

名稱說明
$arg_name請求中的name參數
$args請求中的參數
$binary_remote_addr遠程地址的二進制表示
$body_bytes_sent已發送的消息體字節數
$content_lengthHTTP請求信息裏的"Content-Length"
$content_type請求信息裏的"Content-Type"
$document_root針對當前請求的根路徑設置值
$document_uri與$uri相同; 比如 /test2/test.php
$host請求信息中的"Host",如果請求中沒有Host行,則等於設置的服務器名
$hostname機器名使用 gethostname系統調用的值
$http_cookiecookie 信息
$http_referer引用地址
$http_user_agent客戶端代理信息
$http_via最後一個訪問服務器的Ip地址。
$http_x_forwarded_for相當於網絡訪問路徑
$is_args如果請求行帶有參數,返回“?”,否則返回空字符串
$limit_rate對連接速率的限制
$nginx_version當前運行的nginx版本號
$pidworker進程的PID
$query_string與$args相同
$realpath_root按root指令或alias指令算出的當前請求的絕對路徑。其中的符號鏈接都會解析成真是文件路徑
$remote_addr客戶端IP地址
$remote_port客戶端端口號
$remote_user客戶端用戶名,認證用
$request用戶請求
$request_body這個變量(0.7.58+)包含請求的主要信息。在使用proxy_pass或fastcgi_pass指令的location中比較有意義
$request_body_file客戶端請求主體信息的臨時文件名
$request_completion如果請求成功,設爲"OK";如果請求未完成或者不是一系列請求中最後一部分則設爲空
$request_filename當前請求的文件路徑名,比如/opt/nginx/www/test.php
$request_method請求的方法,比如"GET"、"POST"等
$request_uri請求的URI,帶參數
$scheme所用的協議,比如http或者是https
$server_addr服務器地址,如果沒有用listen指明服務器地址,使用這個變量將發起一次系統調用以取得地址(造成資源浪費)
$server_name請求到達的服務器名
$server_port請求到達的服務器端口號
$server_protocol請求的協議版本,"HTTP/1.0"或"HTTP/1.1"
$uri請求的URI,可能和最初的值有不同,比如經過重定向之類的

其實這還不是全部,Nginx在不停迭代更新是一個原因,還有一個是有些變量太冷門,藉助它們,會有很多玩法。

首先,在OpenResty中如何引用這些變量呢?參考 ngx.var.VARIABLE 小節。

利用這些內置變量,來做一個簡單的數學求和運算例子:

    server {
        listen    80;
        server_name  localhost;

        location /sum {
            #處理業務
           content_by_lua_block {
                local a = tonumber(ngx.var.arg_a) or 0
                local b = tonumber(ngx.var.arg_b) or 0
                ngx.say("sum: ", a + b )
            }
        }
    }

驗證一下:

➜  ~  curl 'http://127.0.0.1/sum?a=11&b=12'
sum: 23

也許你笑了,這個API太簡單沒有實際意義。我們做個簡易防火牆,看看如何開始玩耍。

參看下面示例代碼:

    server {
        listen    80;
        server_name  localhost;

        location /sum {
            # 使用access階段完成准入階段處理
            access_by_lua_block {
                local black_ips = {["127.0.0.1"]=true}

                local ip = ngx.var.remote_addr
                if true == black_ips[ip] then
                    ngx.exit(ngx.HTTP_FORBIDDEN)
                end
            };

            #處理業務
           content_by_lua_block {
                local a = tonumber(ngx.var.arg_a) or 0
                local b = tonumber(ngx.var.arg_b) or 0
                ngx.say("sum:", a + b )
            }
        }
    }

運行測試:

➜  ~  curl '192.168.1.104/sum?a=11&b=12'
sum:23
➜  ~
➜  ~
➜  ~  curl '127.0.0.1/sum?a=11&b=12'
<html>
<head><title>403 Forbidden</title></head>
<body bgcolor="white">
<center><h1>403 Forbidden</h1></center>
<hr><center>openresty/1.9.3.1</center>
</body>
</html>

通過測試結果看到,提取了終端的IP地址後進行限制。擴充一下,就可以支持 IP 地址段,如果再與系統iptables進行配合,那麼就足以達到軟防火牆的目的。

目前爲止,所有的例子都是對Nginx內置變量的獲取,是否可以對其進行設置呢?其實大多數內容都是不允許寫入的,例如剛剛的終端IP地址,在請求中是不允許對其進行更新的。對於可寫的變量中的limit_rate,值得一提,它能完成傳輸速率限制,並且它的影響是單個請求級別。

參看下面示例:

        location /download {
            access_by_lua_block {
                ngx.var.limit_rate = 1000
            };
        }

下載測試:

➜  ~  wget '127.0.0.1/download/1.cab'
--2015-09-13 13:59:51--  http://127.0.0.1/download/1.cab
Connecting to 127.0.0.1... connected.
HTTP request sent, awaiting response... 200 OK
Length: 135802 (133K) [application/octet-stream]
Saving to: '1.cab'

1.cab                6%[===>             ]   8.00K  1.01KB/s   eta 1m 53s
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章