将JSON数据从文件中读入到Lua的Table结构中 - shengnoah/blues GitHub Wiki
一般情况下,我们可以把一些共享的数据,比如说WAF的Rule定义规则存到Share Diction中,rule以JSON的形式存在于文本文件,我们将这些Rule从文本读入到Share Diction中,在这后每次的用户请求时,把Diction中的数据读取到Lua内存变量中和用户的数据进行比较。
下面是对Share Diction的一些简单的操作封装:
local json = require "cjson"
local util = require "cjson.util"
local buffer = {}
function buffer.set(_key,_value)
if _key then
local g_waf = ngx.shared.g_waf
g_waf:set(_key, _value)
end
end
function buffer.get(_key)
if _key then
local g_waf = ngx.shared.g_waf
local value = g_waf:get(_key)
return value
end
end
function buffer.sett(_key,_value)
if type(_value) != "table" then return end
if _key then
local g_waf = ngx.shared.g_waf
local json_value = json.encode(_value)
g_waf:set(_key, json_value)
end
end
function buffer.gett(_key)
if _key then
local g_waf = ngx.shared.g_waf
local value = g_waf:get(_key)
if value then
local table_value = json.decode(value)
return table_value
end
end
end
return buffer
然后,我们可以实验在Content阶段,通过这个库读取Rule结构,从文件读取到Table变量中,然后把Table变量通过转成JSON字符串存到Share Diction中,再从Share Diction中读出到Table中,我们模拟这个过程,然后把这个过程放到init阶段完成。
下面这个函数,只是set key和get key操作。
require "log"
local buffer = require "buffer"
local utils = require "utils.utils"
local Application = require "orc"
app = Application.new()
app:get("/set", function(request,id)
buffer.set("testkey", "testvalue")
local ret = buffer.get("testkey")
ngx.say(ret)
end)
而下面这个操作,是完成set table和get table操作。
app:get("/sett", function(request,id)
local json = require "cjson"
local util = require "cjson.util"
local json_text = util.file_load("./app/data/rules/testcase", env)
local t = json.decode(json_text)
buffer.sett("r1", t)
meta = buffer.gett("r1")
ngx.say(util.serialise_value(meta))
end)
而对Rule到Share Diction的Set操作,我们只在Init阶段做一次。
首先,我们需要的是在conf文件中引入lua_shared_diction和init_by_lua_file这两个配置。
lua_shared_dict g_waf 10m;
init_by_lua_file ./app/init.lua;
然后在app.lua同级目录创建init.lua,加入如下测试代码:
local buffer = require "buffer"
buffer.set("candylab", "Candylab:Blues")
然后,在app.lua中读取candylab这个key的value值:
app:get("/rule", function(request,id)
local ret = buffer.get("candylab")
ngx.say(ret)
end)
以上面说明share diction读取正常,然后从init_by阶段,把rule文件中的json数据读入到Share Diction中。
在init.lua中加入如下代码:
local json = require "cjson"
local util = require "cjson.util"
local json_text = util.file_load("./app/data/rules/testcase", env)
local t = json.decode(json_text)
buffer.sett("rule", t)
然后我们在content阶段,在app.lua加入一个读取动作,读取这个rule。
app:get("/getrule", function(request,id)
local json = require "cjson"
local util = require "cjson.util"
local meta = buffer.gett("rule")
ngx.say(util.serialise_value(meta))
end)
然后发现,引用cjson用的比较难看,都封装到utils/bjson.lua里。
local json = require "cjson"
local util = require "cjson.util"
local bjson = {}
function bjson.loadf(filename, env)
return util.file_load(filename, env)
end
function bjson.decode(json_text)
local ret = json.decode(json_text)
return ret
end
function bjson.encode(table_data)
local ret = json.encode(table_data)
return ret
end
function bjson.pprint(info)
return util.serialise_value(info)
end
return bjson
再看一下改过的代码:
app.lua
app:get("/get_rule", function(request,id)
local ret = buffer.get("candylab")
ngx.say(ret)
end)
app:get("/get_data", function(request,id)
local json_text = bjson.loadf("./app/data/rules/testcase", env)
local t = bjson.decode(json_text)
buffer.sett("r1", t)
meta = buffer.gett("r1")
ngx.say(bjson.pprint(meta))
end)
init.lua
local buffer = require "buffer"
local bjson = require "utils.bjson"
local json_text = bjson.loadf("./app/data/rules/testcase", env)
local t = bjson.decode(json_text)
buffer.sett("rule", t)
buffer.set("candylab", "Candylab:Blues")
到此,一次WAF的Rule加载到Share Diciton的过程我们模拟处理完了, 下一次实验,让用户请求数据与WAF Rule进行对撞演示。