将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进行对撞演示。