一種輕量的openresty路由設計

在使用openresty開發接口的過程會發現一個問題,那就是接口的地址問題怎麼解決,最好一個接口地址對應一個lua文件,也能夠在nginx.conf 配置中使用content_by_lua 來編寫接口邏輯,顯而後者並不合適團隊開發,爲了解決這個問題,因此出現了不少相似的框架,一個比較好用的就是lusty框架,他能夠將url中的某段值自動定義成變量,可是耦合性有點高,當多個接口站點部署在同一個nginx上時,你只能經過修改lusty的目錄結構和app.lua文件,顯然這不是我想要的結果,在網上找到一段很犀利的ngx配置,簡單粗暴,但很是有效。nginx

 

但出於安全性考慮,決定給訪問的接口地址加個白名單功能,不在白名單的地址不容許訪問。api

將白名單功能抽象成一個app_route.lua文件,在初始化的時候須要載入一個白名單列表,具體的ngx配置以下:安全

這裏加載了一個對應目錄的route_config.lua,因爲這個config文件內容較小,因此我把內容直接列了出來:app

--白名單列表
local whitelist = {
    'test1',
    'user/login',
    'user/register'
}
--路由重寫列表
local rewritelist = {
    ['user/([-_a-zA-Z0-9]+)/login'] = 'user/login',
    ['user/([a-zA-Z0-9]+)/register'] = 'user/register'
}
return {
    whitelist = whitelist,
    rewritelist = rewritelist
}

而後在content_by_lua_file 前面加這麼一句代碼:框架

你會發現白名單功能就這麼完成了,並且屢次測試後發現單純的路由查找功能會比lusty快一倍以上。測試

固然也支持簡單的路由重定向功能,本文只是單純的技術分享,若是你有更好的建議也能夠單獨討論。ui

文本是原創做品,轉載記得寫明出處lua

app_route.luaurl

 1 local _M = { _VERSION = '0.1' }
 2 local mt = { __index = _M}
 3 local tinsert = table.insert
 4 local tconcat = table.concat
 5 local tonumber = tonumber
 6 local function uritoken(uri)
 7     local ret = {}
 8     for token in uri:gmatch("[^/.]+") do
 9         tinsert(ret,token)
10     end
11     return ret
12 end
13 
14 function _M.new(self,rconfig)
15     local tab = {}
16     local routeMap = require(rconfig)
17     local route_data = {}
18     local whitelist = routeMap.whitelist
19     for i=1,#whitelist do
20         local ret = uritoken(whitelist[i])
21         if #ret > 0 then
22             tinsert(route_data,tconcat({'^',tconcat(ret,'/'),'$'}))
23         end
24     end
25     local rewritelist = routeMap.rewritelist
26     local x = 1
27     local rewrite_data = {}
28     local rewrite_urls = {}
29     for k,v in pairs(rewritelist) do
30         tinsert(rewrite_data,tconcat({'^(?<z',x,'z>',k,')$'}))
31         tinsert(rewrite_urls,v)
32         x = x + 1
33     end
34     tab.rewrite_urls = rewrite_urls
35     tab.rewrite_pattern = tconcat(rewrite_data,'|')
36     tab.route_pattern = tconcat(route_data,'|')
37     return setmetatable(tab, mt)
38 end
39 
40 function _M.route_verify(self)
41     local uri = ngx.var.api_path
42     local ret = uritoken(uri)
43     uri = tconcat(ret,'/')
44     ngx.var.api_path = uri
45     local m = ngx.re.match(uri,self.route_pattern)
46     if m == nil then
47         m = ngx.re.match(uri,self.rewrite_pattern)
48         if m == nil then
49             ngx.exit(404)
50         else
51             local locant = ngx.re.match(next(m,#m), "^z(\\d+)z")
52             ngx.var.api_path = self.rewrite_urls[tonumber(locant[1])]
53         end
54     end
55 end
56 return _M
相關文章
相關標籤/搜索