在线观看不卡亚洲电影_亚洲妓女99综合网_91青青青亚洲娱乐在线观看_日韩无码高清综合久久

鍍金池/ 教程/ Linux/ Nginx+Lua 開發(fā)入門
Web 開發(fā)實戰(zhàn)2——商品詳情頁
流量復(fù)制 /AB 測試/協(xié)程
常用 Lua 開發(fā)庫 1-redis、mysql、http 客戶端
Lua 模塊開發(fā)
常用 Lua 開發(fā)庫 3-模板渲染
HTTP 服務(wù)
Nginx+Lua 開發(fā)入門
安裝 Nginx+Lua 開發(fā)環(huán)境
Redis/SSDB+Twemproxy 安裝與使用
JSON 庫、編碼轉(zhuǎn)換、字符串處理

Nginx+Lua 開發(fā)入門

Nginx 入門

本文目的是學(xué)習(xí) Nginx+Lua 開發(fā),對于 Nginx 基本知識可以參考如下文章:

nginx 啟動、關(guān)閉、重啟

http://www.cnblogs.com/derekchen/archive/2011/02/17/1957209.html

agentzh 的 Nginx 教程

http://openresty.org/download/agentzh-nginx-tutorials-zhcn.html

Nginx+Lua 入門

http://17173ops.com/2013/11/01/17173-ngx-lua-manual.shtml

nginx 配置指令的執(zhí)行順序

http://zhongfox.github.io/blog/server/2013/05/15/nginx-exec-order/

nginx 與 lua 的執(zhí)行順序和步驟說明

http://www.mrhaoting.com/?p=157

Nginx 配置文件 nginx.conf 中文詳解

http://www.ha97.com/5194.html

Tengine 的 Nginx 開發(fā)從入門到精通

http://tengine.taobao.org/book/

官方文檔

http://wiki.nginx.org/Configuration

Lua 入門

本文目的是學(xué)習(xí) Nginx+Lua 開發(fā),對于 Lua 基本知識可以參考如下文章:

Lua 簡明教程

http://coolshell.cn/articles/10739.html

lua 在線 lua 學(xué)習(xí)教程

http://book.luaer.cn/

Lua 5.1 參考手冊

http://www.codingnow.com/2000/download/lua_manual.html

Lua 5.3 參考手冊

http://cloudwu.github.io/lua53doc/

Nginx Lua API

和一般的 Web Server 類似,我們需要接收請求、處理并輸出響應(yīng)。而對于請求我們需要獲取如請求參數(shù)、請求頭、Body 體等信息;而對于處理就是調(diào)用相應(yīng)的 Lua 代碼即可;輸出響應(yīng)需要進(jìn)行響應(yīng)狀態(tài)碼、響應(yīng)頭和響應(yīng)內(nèi)容體的輸出。因此我們從如上幾個點出發(fā)即可。

接收請求

example.conf 配置文件

Java 代碼 收藏代碼

location ~ /lua_request/(\d+)/(\d+) {  
    #設(shè)置nginx變量  
    set $a $1;   
    set $b $host;  
    default_type "text/html";  
    #nginx內(nèi)容處理  
    content_by_lua_file /usr/example/lua/test_request.lua;  
    #內(nèi)容體處理完成后調(diào)用  
    echo_after_body "ngx.var.b $b";  
}    

test_request.lua

Java 代碼 收藏代碼

--nginx變量  
local var = ngx.var  
ngx.say("ngx.var.a : ", var.a, "<br/>")  
ngx.say("ngx.var.b : ", var.b, "<br/>")  
ngx.say("ngx.var[2] : ", var[2], "<br/>")  
ngx.var.b = 2;  

ngx.say("<br/>")  

--請求頭  
local headers = ngx.req.get_headers()  
ngx.say("headers begin", "<br/>")  
ngx.say("Host : ", headers["Host"], "<br/>")  
ngx.say("user-agent : ", headers["user-agent"], "<br/>")  
ngx.say("user-agent : ", headers.user_agent, "<br/>")  
for k,v in pairs(headers) do  
    if type(v) == "table" then  
        ngx.say(k, " : ", table.concat(v, ","), "<br/>")  
    else  
        ngx.say(k, " : ", v, "<br/>")  
    end  
end  
ngx.say("headers end", "<br/>")  
ngx.say("<br/>")  

--get請求uri參數(shù)  
ngx.say("uri args begin", "<br/>")  
local uri_args = ngx.req.get_uri_args()  
for k, v in pairs(uri_args) do  
    if type(v) == "table" then  
        ngx.say(k, " : ", table.concat(v, ", "), "<br/>")  
    else  
        ngx.say(k, ": ", v, "<br/>")  
    end  
end  
ngx.say("uri args end", "<br/>")  
ngx.say("<br/>")  

--post請求參數(shù)  
ngx.req.read_body()  
ngx.say("post args begin", "<br/>")  
local post_args = ngx.req.get_post_args()  
for k, v in pairs(post_args) do  
    if type(v) == "table" then  
        ngx.say(k, " : ", table.concat(v, ", "), "<br/>")  
    else  
        ngx.say(k, ": ", v, "<br/>")  
    end  
end  
ngx.say("post args end", "<br/>")  
ngx.say("<br/>")  
--請求的http協(xié)議版本  
ngx.say("ngx.req.http_version : ", ngx.req.http_version(), "<br/>")  
--請求方法  
ngx.say("ngx.req.get_method : ", ngx.req.get_method(), "<br/>")  
--原始的請求頭內(nèi)容  
ngx.say("ngx.req.raw_header : ",  ngx.req.raw_header(), "<br/>")  
--請求的body內(nèi)容體  
ngx.say("ngx.req.get_body_data() : ", ngx.req.get_body_data(), "<br/>")  
ngx.say("<br/>")   

ngx.var : nginx 變量,如果要賦值如 ngx.var.b = 2,此變量必須提前聲明;另外對于 nginx location 中使用正則捕獲的捕獲組可以使用 ngx.var [捕獲組數(shù)字]獲??;

ngx.req.get_headers:獲取請求頭,默認(rèn)只獲取前100,如果想要獲取所以可以調(diào)用ngx.req.get_headers(0);獲取帶中劃線的請求頭時請使用如 headers.user_agent 這種方式;如果一個請求頭有多個值,則返回的是 table;

ngx.req.get_uri_args:獲取 url 請求參數(shù),其用法和 get_headers 類似;

ngx.req.get_post_args:獲取 post 請求內(nèi)容體,其用法和 get_headers 類似,但是必須提前調(diào)用 ngx.req.read_body() 來讀取 body 體(也可以選擇在 nginx 配置文件使用lua_need_request_body on;開啟讀取 body 體,但是官方不推薦);

ngx.req.raw_header:未解析的請求頭字符串;

ngx.req.get_body_data:為解析的請求 body 體內(nèi)容字符串。

如上方法處理一般的請求基本夠用了。另外在讀取 post 內(nèi)容體時根據(jù)實際情況設(shè)置 client_body_buffer_size 和 client_max_body_size 來保證內(nèi)容在內(nèi)存而不是在文件中。

使用如下腳本測試

Java 代碼 收藏代碼

wget --post-data 'a=1&b=2' 'http://127.0.0.1/lua_request/1/2?a=3&b=4' -O -   

輸出響應(yīng)

example.conf 配置文件

Java 代碼 收藏代碼

location /lua_response_1 {  
    default_type "text/html";  
    content_by_lua_file /usr/example/lua/test_response_1.lua;  
}    

test_response_1.lua

Java 代碼 收藏代碼

--寫響應(yīng)頭  
ngx.header.a = "1"  
--多個響應(yīng)頭可以使用table  
ngx.header.b = {"2", "3"}  
--輸出響應(yīng)  
ngx.say("a", "b", "<br/>")  
ngx.print("c", "d", "<br/>")  
--200狀態(tài)碼退出  
return ngx.exit(200)  
ngx.header:輸出響應(yīng)頭;
ngx.print:輸出響應(yīng)內(nèi)容體;
ngx.say:通ngx.print,但是會最后輸出一個換行符;
ngx.exit:指定狀態(tài)碼退出。

example.conf 配置文件

Java 代碼 收藏代碼

location /lua_response_2 {  
    default_type "text/html";  
    content_by_lua_file /usr/example/lua/test_response_2.lua;  
}  

test_response_2.lua

Java 代碼 收藏代碼

ngx.redirect("http://jd.com", 302)    

ngx.redirect:重定向;

ngx.status= 狀態(tài)碼,設(shè)置響應(yīng)的狀態(tài)碼;ngx.resp.get_headers() 獲取設(shè)置的響應(yīng)狀態(tài)碼;ngx.send_headers() 發(fā)送響應(yīng)狀態(tài)碼,當(dāng)調(diào)用 ngx.say/ngx.print 時自動發(fā)送響應(yīng)狀態(tài)碼;可以通過 ngx.headers_sent=true 判斷是否發(fā)送了響應(yīng)狀態(tài)碼。

其他 API

example.conf 配置文件

Java 代碼 收藏代碼

location /lua_other {  
    default_type "text/html";  
    content_by_lua_file /usr/example/lua/test_other.lua;  
}  

test_other.lua

Java 代碼 收藏代碼

--未經(jīng)解碼的請求uri  
local request_uri = ngx.var.request_uri;  
ngx.say("request_uri : ", request_uri, "<br/>");  
--解碼  
ngx.say("decode request_uri : ", ngx.unescape_uri(request_uri), "<br/>");  
--MD5  
ngx.say("ngx.md5 : ", ngx.md5("123"), "<br/>")  
--http time  
ngx.say("ngx.http_time : ", ngx.http_time(ngx.time()), "<br/>")  
  • ngx.escape_uri/ngx.unescape_uri : uri 編碼解碼;
  • ngx.encode_args/ngx.decode_args:參數(shù)編碼解碼;
  • ngx.encode_base64/ngx.decode_base64:BASE64 編碼解碼;
  • ngx.re.match:nginx 正則表達(dá)式匹配;

更多 Nginx Lua API 請參考 http://wiki.nginx.org/HttpLuaModule#Nginx_API_for_Lua。

Nginx 全局內(nèi)存

使用過如 Java 的朋友可能知道如 Ehcache 等這種進(jìn)程內(nèi)本地緩存,Nginx 是一個 Master 進(jìn)程多個 Worker 進(jìn)程的工作方式,因此我們可能需要在多個 Worker 進(jìn)程中共享數(shù)據(jù),那么此時就可以使用 ngx.shared.DICT 來實現(xiàn)全局內(nèi)存共享。

首先在 nginx.conf 的 http 部分分配內(nèi)存大小

Java 代碼 收藏代碼

\#共享全局變量,在所有worker間共享  
lua_shared_dict shared_data 1m;  

example.conf 配置文件

Java 代碼 收藏代碼

location /lua_shared_dict {  
    default_type "text/html";  
    content_by_lua_file /usr/example/lua/test_lua_shared_dict.lua;  
}    

test_lua_shared_dict.lua

Java 代碼 收藏代碼

--1、獲取全局共享內(nèi)存變量  
local shared_data = ngx.shared.shared_data  

--2、獲取字典值  
local i = shared_data:get("i")  
if not i then  
    i = 1  
    --3、惰性賦值  
    shared_data:set("i", i)  
    ngx.say("lazy set i ", i, "<br/>")  
end  
--遞增  
i = shared_data:incr("i", 1)  
ngx.say("i=", i, "<br/>")   

更多 API 請參考 http://wiki.nginx.org/HttpLuaModule#ngx.shared.DICT。

到此基本的 Nginx Lua API 就學(xué)完了,對于請求處理和輸出響應(yīng)如上介紹的 API 完全夠用了,更多 API 請參考官方文檔。

Nginx Lua 模塊指令

Nginx 共11個處理階段,而相應(yīng)的處理階段是可以做插入式處理,即可插拔式架構(gòu);另外指令可以在 http、server、server if、location、location if 幾個范圍進(jìn)行配置:

指令

所處處理階段

使用范圍

解釋

init_by_lua

init_by_lua_file

loading-config

http

nginx Master進(jìn)程加載配置時執(zhí)行;

通常用于初始化全局配置/預(yù)加載Lua模塊

init_worker_by_lua

init_worker_by_lua_file

starting-worker

http

每個Nginx Worker進(jìn)程啟動時調(diào)用的計時器,如果Master進(jìn)程不允許則只會在init_by_lua之后調(diào)用;

通常用于定時拉取配置/數(shù)據(jù),或者后端服務(wù)的健康檢查

set_by_lua

set_by_lua_file

rewrite

server,server if,location,location if

設(shè)置nginx變量,可以實現(xiàn)復(fù)雜的賦值邏輯;此處是阻塞的,Lua代碼要做到非???;

rewrite_by_lua

rewrite_by_lua_file

rewrite tail

http,server,location,location if

rrewrite階段處理,可以實現(xiàn)復(fù)雜的轉(zhuǎn)發(fā)/重定向邏輯;

access_by_lua

access_by_lua_file

access tail

http,server,location,location if

請求訪問階段處理,用于訪問控制

content_by_lua

content_by_lua_file

content

location,location if

內(nèi)容處理器,接收請求處理并輸出響應(yīng)

header_filter_by_lua

header_filter_by_lua_file

output-header-filter

http,server,location,location if

設(shè)置header和cookie

body_filter_by_lua

body_filter_by_lua_file

output-body-filter

http,server,location,location if

對響應(yīng)數(shù)據(jù)進(jìn)行過濾,比如截斷、替換。

log_by_lua

log_by_lua_file

log

http,server,location,location if

log階段處理,比如記錄訪問量/統(tǒng)計平均響應(yīng)時間

更詳細(xì)的解釋請參考 http://wiki.nginx.org/HttpLuaModule#Directives。如上指令很多并不常用,因此我們只拿其中的一部分做演示。

init_by_lua

每次 Nginx 重新加載配置時執(zhí)行,可以用它來完成一些耗時模塊的加載,或者初始化一些全局配置;在 Master 進(jìn)程創(chuàng)建 Worker 進(jìn)程時,此指令中加載的全局變量會進(jìn)行 Copy-OnWrite,即會復(fù)制到所有全局變量到 Worker 進(jìn)程。

nginx.conf 配置文件中的 http 部分添加如下代碼

Java 代碼 收藏代碼

\#共享全局變量,在所有worker間共享  
lua_shared_dict shared_data 1m;  

init_by_lua_file /usr/example/lua/init.lua;  

init.lua

Java 代碼 收藏代碼

--初始化耗時的模塊  
local redis = require 'resty.redis'  
local cjson = require 'cjson'  

--全局變量,不推薦  
count = 1  

--共享全局內(nèi)存  
local shared_data = ngx.shared.shared_data  
shared_data:set("count", 1)  

test.lua

Java 代碼 收藏代碼

count = count + 1  
ngx.say("global variable : ", count)  
local shared_data = ngx.shared.shared_data  
ngx.say(", shared memory : ", shared_data:get("count"))  
shared_data:incr("count", 1)  
ngx.say("hello world")  

訪問如 http://192.168.1.2/lua 會發(fā)現(xiàn)全局變量一直不變,而共享內(nèi)存一直遞增

global variable : 2 , shared memory : 8 hello world

另外注意一定在生產(chǎn)環(huán)境開啟 lua_code_cache,否則每個請求都會創(chuàng)建 Lua VM 實例。

init_worker_by_lua

用于啟動一些定時任務(wù),比如心跳檢查,定時拉取服務(wù)器配置等等;此處的任務(wù)是跟 Worker 進(jìn)程數(shù)量有關(guān)系的,比如有2個 Worker 進(jìn)程那么就會啟動兩個完全一樣的定時任務(wù)。

nginx.conf 配置文件中的 http 部分添加如下代碼

Java 代碼 收藏代碼

init_worker_by_lua_file /usr/example/lua/init_worker.lua;  

init_worker.lua

Java 代碼 收藏代碼

local count = 0  
local delayInSeconds = 3  
local heartbeatCheck = nil  

heartbeatCheck = function(args)  
   count = count + 1  
   ngx.log(ngx.ERR, "do check ", count)  

   local ok, err = ngx.timer.at(delayInSeconds, heartbeatCheck)  

   if not ok then  
      ngx.log(ngx.ERR, "failed to startup heartbeart worker...", err)  
   end  
end  

heartbeatCheck()  

ngx.timer.at:延時調(diào)用相應(yīng)的回調(diào)方法;ngx.timer.at(秒單位延時,回調(diào)函數(shù),回調(diào)函數(shù)的參數(shù)列表);可以將延時設(shè)置為0即得到一個立即執(zhí)行的任務(wù),任務(wù)不會在當(dāng)前請求中執(zhí)行不會阻塞當(dāng)前請求,而是在一個輕量級線程中執(zhí)行。

另外根據(jù)實際情況設(shè)置如下指令

  • lua_max_pending_timers 1024; #最大等待任務(wù)數(shù)
  • lua_max_running_timers 256; #最大同時運行任務(wù)數(shù)

set_by_lua

設(shè)置 nginx 變量,我們用的 set 指令即使配合 if 指令也很難實現(xiàn)負(fù)責(zé)的賦值邏輯;

example.conf 配置文件

Java 代碼 收藏代碼

location /lua_set_1 {  
    default_type "text/html";  
    set_by_lua_file $num /usr/example/lua/test_set_1.lua;  
    echo $num;  
}    

set_by_lua_file:語法 set_by_lua_file $var lua_file arg1 arg2...; 在 lua代碼中可以實現(xiàn)所有復(fù)雜的邏輯,但是要執(zhí)行速度很快,不要阻塞;

test_set_1.lua

Java 代碼 收藏代碼

local uri_args = ngx.req.get_uri_args()  
local i = uri_args["i"] or 0  
local j = uri_args["j"] or 0  

return i + j   

得到請求參數(shù)進(jìn)行相加然后返回。

訪問如 http://192.168.1.2/lua_set_1?i=1&j=10 進(jìn)行測試。 如果我們用純 set 指令是無法實現(xiàn)的。

再舉個實際例子,我們實際工作時經(jīng)常涉及到網(wǎng)站改版,有時候需要新老并存,或者切一部分流量到新版

首先在 example.conf 中使用 map 指令來映射 host 到指定 nginx 變量,方便我們測試

Java 代碼 收藏代碼

############ 測試時使用的動態(tài)請求  
map $host $item_dynamic {  
    default                     "0";  
    item2014.jd.com            "1";  
}   

如綁定 hosts

  • 192.168.1.2 item.jd.com;
  • 192.168.1.2 item2014.jd.com;

此時我們想訪問 item2014.jd.com 時訪問新版,那么我們可以簡單的使用如

Java 代碼 收藏代碼

if ($item_dynamic = "1") {  
   proxy_pass http://new;  
}  
proxy_pass http://old;  

但是我們想把商品編號為 8 位(比如品類為圖書的)沒有改版完成,需要按照相應(yīng)規(guī)則跳轉(zhuǎn)到老版,但是其他的到新版;雖然使用 if 指令能實現(xiàn),但是比較麻煩,基本需要這樣

Java 代碼 收藏代碼

set jump "0";  
if($item_dynamic = "1") {  
    set $jump "1";  
}  
if(uri ~ "^/6[0-9]{7}.html") {  
   set $jump "${jump}2";  
}   
\#非強制訪問新版,且訪問指定范圍的商品  
if (jump == "02") {  
   proxy_pass http://old;  
}  
proxy_pass http://new;   

以上規(guī)則還是比較簡單的,如果涉及到更復(fù)雜的多重 if/else 或嵌套 if/else 實現(xiàn)起來就更痛苦了,可能需要到后端去做了;此時我們就可以借助 lua 了:

Java 代碼 收藏代碼

set_by_lua $to_book '  
     local ngx_match = ngx.re.match  
     local var = ngx.var  
     local skuId = var.skuId  
     local r = var.item_dynamic ~= "1" and ngx.re.match(skuId, "^[0-9]{8}$")  
     if r then return "1" else return "0" end;  
';  
set_by_lua $to_mvd '  
     local ngx_match = ngx.re.match  
     local var = ngx.var  
     local skuId = var.skuId  
     local r = var.item_dynamic ~= "1" and ngx.re.match(skuId, "^[0-9]{9}$")  
     if r then return "1" else return "0" end;  
';  
\#自營圖書  
if ($to_book) {  
    proxy_pass http://127.0.0.1/old_book/$skuId.html;  
}  
\#自營音像  
if ($to_mvd) {  
    proxy_pass http://127.0.0.1/old_mvd/$skuId.html;  
}  
\#默認(rèn)  
proxy_pass http://127.0.0.1/proxy/$skuId.html;  

rewrite_by_lua

執(zhí)行內(nèi)部 URL 重寫或者外部重定向,典型的如偽靜態(tài)化的 URL 重寫。其默認(rèn)執(zhí)行在 rewrite 處理階段的最后。

example.conf 配置文件

Java 代碼 收藏代碼

location /lua_rewrite_1 {  
    default_type "text/html";  
    rewrite_by_lua_file /usr/example/lua/test_rewrite_1.lua;  
    echo "no rewrite";  
}  

test_rewrite_1.lua

Java 代碼 收藏代碼

if ngx.req.get_uri_args()["jump"] == "1" then  
   return ngx.redirect("http://www.jd.com?jump=1", 302)  
end    

當(dāng)我們請求 http://192.168.1.2/lua_rewrite_1 時發(fā)現(xiàn)沒有跳轉(zhuǎn),而請求 http://192.168.1.2/lua_rewrite_1?jump=1 時發(fā)現(xiàn)跳轉(zhuǎn)到京東首頁了。 此處需要301/302跳轉(zhuǎn)根據(jù)自己需求定義。

example.conf 配置文件

Java 代碼 收藏代碼

location /lua_rewrite_2 {  
    default_type "text/html";  
    rewrite_by_lua_file /usr/example/lua/test_rewrite_2.lua;  
    echo "rewrite2 uri : $uri, a : $arg_a";  
}  

test_rewrite_2.lua

Java 代碼 收藏代碼

if ngx.req.get_uri_args()["jump"] == "1" then  
   ngx.req.set_uri("/lua_rewrite_3", false);  
   ngx.req.set_uri("/lua_rewrite_4", false);  
   ngx.req.set_uri_args({a = 1, b = 2});  
end     

ngx.req.set_uri(uri, false):可以內(nèi)部重寫 uri(可以帶參數(shù)),等價于 rewrite ^ /lua_rewrite_3;通過配合 if/else 可以實現(xiàn) rewrite ^ /lua_rewrite_3 break;這種功能;此處兩者都是 location 內(nèi)部 url 重寫,不會重新發(fā)起新的 location 匹配;

ngx.req.set_uri_args:重寫請求參數(shù),可以是字符串(a=1&b=2)也可以是 table;

訪問如 http://192.168.1.2/lua_rewrite_2?jump=0 時得到響應(yīng) rewrite2 uri : /lua_rewrite_2, a :

訪問如 http://192.168.1.2/lua_rewrite_2?jump=1 時得到響應(yīng) rewrite2 uri : /lua_rewrite_4, a : 1

example.conf 配置文件

Java 代碼 收藏代碼

location /lua_rewrite_3 {  
    default_type "text/html";  
    rewrite_by_lua_file /usr/example/lua/test_rewrite_3.lua;  
    echo "rewrite3 uri : $uri";  
}  

c test_rewrite_3.lua

Java 代碼 收藏代碼

if ngx.req.get_uri_args()["jump"] == "1" then  
   ngx.req.set_uri("/lua_rewrite_4", true);  
   ngx.log(ngx.ERR, "=========")  
   ngx.req.set_uri_args({a = 1, b = 2});  
end    

ngx.req.set_uri(uri, true):可以內(nèi)部重寫 uri,即會發(fā)起新的匹配 location 請求,等價于 rewrite ^ /lua_rewrite_4 last;此處看 error log 是看不到我們記錄的log。

所以請求如 http://192.168.1.2/lua_rewrite_3?jump=1 會到新的 location 中得到響應(yīng),此處沒有 /lua_rewrite_4,所以匹配到 /lua 請求,得到類似如下的響應(yīng) global variable : 2 , shared memory : 1 hello world

rewrite ^ /lua_rewrite_3;                 等價于  ngx.req.set_uri("/lua_rewrite_3", false);
rewrite ^ /lua_rewrite_3 break;       等價于  ngx.req.set_uri("/lua_rewrite_3", false); 加 if/else判斷/break/return
rewrite ^ /lua_rewrite_4 last;           等價于  ngx.req.set_uri("/lua_rewrite_4", true);

注意,在使用 rewrite_by_lua 時,開啟 rewrite_log on;后也看不到相應(yīng)的 rewrite log。

access_by_lua

用于訪問控制,比如我們只允許內(nèi)網(wǎng) ip 訪問,可以使用如下形式

Java 代碼 收藏代碼

allow     127.0.0.1;  
allow     10.0.0.0/8;  
allow     192.168.0.0/16;  
allow     172.16.0.0/12;  
deny      all;  

example.conf 配置文件

Java 代碼 收藏代碼

location /lua_access {  
    default_type "text/html";  
    access_by_lua_file /usr/example/lua/test_access.lua;  
    echo "access";  
}  

test_access.lua

Java 代碼 收藏代碼

if ngx.req.get_uri_args()["token"] ~= "123" then  
   return ngx.exit(403)  
end    

即如果訪問如 http://192.168.1.2/lua_access?token=234 將得到 403 Forbidden 的響應(yīng)。這樣我們可以根據(jù)如 cookie/ 用戶 token 來決定是否有訪問權(quán)限。

content_by_lua

此指令之前已經(jīng)用過了,此處就不講解了。

另外在使用 PCRE 進(jìn)行正則匹配時需要注意正則的寫法,具體規(guī)則請參考 http://wiki.nginx.org/HttpLuaModule中的Special PCRE Sequences部 分。還有其他的注意事項也請閱讀官方文檔。