mirror of
https://github.com/onionltd/EndGame.git
synced 2025-08-02 03:46:05 -04:00
Init commit
This commit is contained in:
commit
770d6da100
40 changed files with 6875 additions and 0 deletions
258
resty/core/base.lua
Normal file
258
resty/core/base.lua
Normal file
|
@ -0,0 +1,258 @@
|
|||
-- Copyright (C) Yichun Zhang (agentzh)
|
||||
|
||||
|
||||
local ffi = require 'ffi'
|
||||
local ffi_new = ffi.new
|
||||
local error = error
|
||||
local select = select
|
||||
local ceil = math.ceil
|
||||
local subsystem = ngx.config.subsystem
|
||||
|
||||
|
||||
local str_buf_size = 4096
|
||||
local str_buf
|
||||
local size_ptr
|
||||
local FREE_LIST_REF = 0
|
||||
|
||||
|
||||
if subsystem == 'http' then
|
||||
if not ngx.config
|
||||
or not ngx.config.ngx_lua_version
|
||||
or ngx.config.ngx_lua_version ~= 10016
|
||||
then
|
||||
error("ngx_http_lua_module 0.10.16 required")
|
||||
end
|
||||
|
||||
elseif subsystem == 'stream' then
|
||||
if not ngx.config
|
||||
or not ngx.config.ngx_lua_version
|
||||
or ngx.config.ngx_lua_version ~= 8
|
||||
then
|
||||
error("ngx_stream_lua_module 0.0.8 required")
|
||||
end
|
||||
|
||||
else
|
||||
error("ngx_http_lua_module 0.10.16 or "
|
||||
.. "ngx_stream_lua_module 0.0.8 required")
|
||||
end
|
||||
|
||||
|
||||
if string.find(jit.version, " 2.0", 1, true) then
|
||||
ngx.log(ngx.ALERT, "use of lua-resty-core with LuaJIT 2.0 is ",
|
||||
"not recommended; use LuaJIT 2.1+ instead")
|
||||
end
|
||||
|
||||
|
||||
local ok, new_tab = pcall(require, "table.new")
|
||||
if not ok then
|
||||
new_tab = function (narr, nrec) return {} end
|
||||
end
|
||||
|
||||
|
||||
local clear_tab
|
||||
ok, clear_tab = pcall(require, "table.clear")
|
||||
if not ok then
|
||||
local pairs = pairs
|
||||
clear_tab = function (tab)
|
||||
for k, _ in pairs(tab) do
|
||||
tab[k] = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
-- XXX for now LuaJIT 2.1 cannot compile require()
|
||||
-- so we make the fast code path Lua only in our own
|
||||
-- wrapper so that most of the require() calls in hot
|
||||
-- Lua code paths can be JIT compiled.
|
||||
do
|
||||
local orig_require = require
|
||||
local pkg_loaded = package.loaded
|
||||
local function my_require(name)
|
||||
local mod = pkg_loaded[name]
|
||||
if mod then
|
||||
return mod
|
||||
end
|
||||
return orig_require(name)
|
||||
end
|
||||
getfenv(0).require = my_require
|
||||
end
|
||||
|
||||
|
||||
if not pcall(ffi.typeof, "ngx_str_t") then
|
||||
ffi.cdef[[
|
||||
typedef struct {
|
||||
size_t len;
|
||||
const unsigned char *data;
|
||||
} ngx_str_t;
|
||||
]]
|
||||
end
|
||||
|
||||
|
||||
if subsystem == 'http' then
|
||||
if not pcall(ffi.typeof, "ngx_http_request_t") then
|
||||
ffi.cdef[[
|
||||
typedef struct ngx_http_request_s ngx_http_request_t;
|
||||
]]
|
||||
end
|
||||
|
||||
if not pcall(ffi.typeof, "ngx_http_lua_ffi_str_t") then
|
||||
ffi.cdef[[
|
||||
typedef struct {
|
||||
int len;
|
||||
const unsigned char *data;
|
||||
} ngx_http_lua_ffi_str_t;
|
||||
]]
|
||||
end
|
||||
|
||||
elseif subsystem == 'stream' then
|
||||
if not pcall(ffi.typeof, "ngx_stream_lua_request_t") then
|
||||
ffi.cdef[[
|
||||
typedef struct ngx_stream_lua_request_s ngx_stream_lua_request_t;
|
||||
]]
|
||||
end
|
||||
|
||||
if not pcall(ffi.typeof, "ngx_stream_lua_ffi_str_t") then
|
||||
ffi.cdef[[
|
||||
typedef struct {
|
||||
int len;
|
||||
const unsigned char *data;
|
||||
} ngx_stream_lua_ffi_str_t;
|
||||
]]
|
||||
end
|
||||
|
||||
else
|
||||
error("unknown subsystem: " .. subsystem)
|
||||
end
|
||||
|
||||
|
||||
local c_buf_type = ffi.typeof("char[?]")
|
||||
|
||||
|
||||
local _M = new_tab(0, 18)
|
||||
|
||||
|
||||
_M.version = "0.1.17"
|
||||
_M.new_tab = new_tab
|
||||
_M.clear_tab = clear_tab
|
||||
|
||||
|
||||
local errmsg
|
||||
|
||||
|
||||
function _M.get_errmsg_ptr()
|
||||
if not errmsg then
|
||||
errmsg = ffi_new("char *[1]")
|
||||
end
|
||||
return errmsg
|
||||
end
|
||||
|
||||
|
||||
if not ngx then
|
||||
error("no existing ngx. table found")
|
||||
end
|
||||
|
||||
|
||||
function _M.set_string_buf_size(size)
|
||||
if size <= 0 then
|
||||
return
|
||||
end
|
||||
if str_buf then
|
||||
str_buf = nil
|
||||
end
|
||||
str_buf_size = ceil(size)
|
||||
end
|
||||
|
||||
|
||||
function _M.get_string_buf_size()
|
||||
return str_buf_size
|
||||
end
|
||||
|
||||
|
||||
function _M.get_size_ptr()
|
||||
if not size_ptr then
|
||||
size_ptr = ffi_new("size_t[1]")
|
||||
end
|
||||
|
||||
return size_ptr
|
||||
end
|
||||
|
||||
|
||||
function _M.get_string_buf(size, must_alloc)
|
||||
-- ngx.log(ngx.ERR, "str buf size: ", str_buf_size)
|
||||
if size > str_buf_size or must_alloc then
|
||||
return ffi_new(c_buf_type, size)
|
||||
end
|
||||
|
||||
if not str_buf then
|
||||
str_buf = ffi_new(c_buf_type, str_buf_size)
|
||||
end
|
||||
|
||||
return str_buf
|
||||
end
|
||||
|
||||
|
||||
function _M.ref_in_table(tb, key)
|
||||
if key == nil then
|
||||
return -1
|
||||
end
|
||||
local ref = tb[FREE_LIST_REF]
|
||||
if ref and ref ~= 0 then
|
||||
tb[FREE_LIST_REF] = tb[ref]
|
||||
|
||||
else
|
||||
ref = #tb + 1
|
||||
end
|
||||
tb[ref] = key
|
||||
|
||||
-- print("ref key_id returned ", ref)
|
||||
return ref
|
||||
end
|
||||
|
||||
|
||||
function _M.allows_subsystem(...)
|
||||
local total = select("#", ...)
|
||||
|
||||
for i = 1, total do
|
||||
if select(i, ...) == subsystem then
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
error("unsupported subsystem: " .. subsystem, 2)
|
||||
end
|
||||
|
||||
|
||||
_M.FFI_OK = 0
|
||||
_M.FFI_NO_REQ_CTX = -100
|
||||
_M.FFI_BAD_CONTEXT = -101
|
||||
_M.FFI_ERROR = -1
|
||||
_M.FFI_AGAIN = -2
|
||||
_M.FFI_BUSY = -3
|
||||
_M.FFI_DONE = -4
|
||||
_M.FFI_DECLINED = -5
|
||||
|
||||
|
||||
do
|
||||
local exdata
|
||||
|
||||
ok, exdata = pcall(require, "thread.exdata")
|
||||
if ok and exdata then
|
||||
function _M.get_request()
|
||||
local r = exdata()
|
||||
if r ~= nil then
|
||||
return r
|
||||
end
|
||||
end
|
||||
|
||||
else
|
||||
local getfenv = getfenv
|
||||
|
||||
function _M.get_request()
|
||||
return getfenv(0).__ngx_req
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
return _M
|
115
resty/core/base64.lua
Normal file
115
resty/core/base64.lua
Normal file
|
@ -0,0 +1,115 @@
|
|||
-- Copyright (C) Yichun Zhang (agentzh)
|
||||
|
||||
|
||||
local ffi = require "ffi"
|
||||
local base = require "resty.core.base"
|
||||
|
||||
|
||||
local C = ffi.C
|
||||
local ffi_string = ffi.string
|
||||
local ngx = ngx
|
||||
local type = type
|
||||
local error = error
|
||||
local floor = math.floor
|
||||
local tostring = tostring
|
||||
local get_string_buf = base.get_string_buf
|
||||
local get_size_ptr = base.get_size_ptr
|
||||
local subsystem = ngx.config.subsystem
|
||||
|
||||
|
||||
local ngx_lua_ffi_encode_base64
|
||||
local ngx_lua_ffi_decode_base64
|
||||
|
||||
|
||||
if subsystem == "http" then
|
||||
ffi.cdef[[
|
||||
size_t ngx_http_lua_ffi_encode_base64(const unsigned char *src,
|
||||
size_t len, unsigned char *dst,
|
||||
int no_padding);
|
||||
|
||||
int ngx_http_lua_ffi_decode_base64(const unsigned char *src,
|
||||
size_t len, unsigned char *dst,
|
||||
size_t *dlen);
|
||||
]]
|
||||
|
||||
ngx_lua_ffi_encode_base64 = C.ngx_http_lua_ffi_encode_base64
|
||||
ngx_lua_ffi_decode_base64 = C.ngx_http_lua_ffi_decode_base64
|
||||
|
||||
elseif subsystem == "stream" then
|
||||
ffi.cdef[[
|
||||
size_t ngx_stream_lua_ffi_encode_base64(const unsigned char *src,
|
||||
size_t len, unsigned char *dst,
|
||||
int no_padding);
|
||||
|
||||
int ngx_stream_lua_ffi_decode_base64(const unsigned char *src,
|
||||
size_t len, unsigned char *dst,
|
||||
size_t *dlen);
|
||||
]]
|
||||
|
||||
ngx_lua_ffi_encode_base64 = C.ngx_stream_lua_ffi_encode_base64
|
||||
ngx_lua_ffi_decode_base64 = C.ngx_stream_lua_ffi_decode_base64
|
||||
end
|
||||
|
||||
|
||||
local function base64_encoded_length(len, no_padding)
|
||||
return no_padding and floor((len * 8 + 5) / 6) or
|
||||
floor((len + 2) / 3) * 4
|
||||
end
|
||||
|
||||
|
||||
ngx.encode_base64 = function (s, no_padding)
|
||||
if type(s) ~= 'string' then
|
||||
if not s then
|
||||
s = ''
|
||||
else
|
||||
s = tostring(s)
|
||||
end
|
||||
end
|
||||
|
||||
local slen = #s
|
||||
local no_padding_bool = false;
|
||||
local no_padding_int = 0;
|
||||
|
||||
if no_padding then
|
||||
if no_padding ~= true then
|
||||
local typ = type(no_padding)
|
||||
error("bad no_padding: boolean expected, got " .. typ, 2)
|
||||
end
|
||||
|
||||
no_padding_bool = true
|
||||
no_padding_int = 1;
|
||||
end
|
||||
|
||||
local dlen = base64_encoded_length(slen, no_padding_bool)
|
||||
local dst = get_string_buf(dlen)
|
||||
local r_dlen = ngx_lua_ffi_encode_base64(s, slen, dst, no_padding_int)
|
||||
-- if dlen ~= r_dlen then error("discrepancy in len") end
|
||||
return ffi_string(dst, r_dlen)
|
||||
end
|
||||
|
||||
|
||||
local function base64_decoded_length(len)
|
||||
return floor((len + 3) / 4) * 3
|
||||
end
|
||||
|
||||
|
||||
ngx.decode_base64 = function (s)
|
||||
if type(s) ~= 'string' then
|
||||
error("string argument only", 2)
|
||||
end
|
||||
local slen = #s
|
||||
local dlen = base64_decoded_length(slen)
|
||||
-- print("dlen: ", tonumber(dlen))
|
||||
local dst = get_string_buf(dlen)
|
||||
local pdlen = get_size_ptr()
|
||||
local ok = ngx_lua_ffi_decode_base64(s, slen, dst, pdlen)
|
||||
if ok == 0 then
|
||||
return nil
|
||||
end
|
||||
return ffi_string(dst, pdlen[0])
|
||||
end
|
||||
|
||||
|
||||
return {
|
||||
version = base.version
|
||||
}
|
101
resty/core/ctx.lua
Normal file
101
resty/core/ctx.lua
Normal file
|
@ -0,0 +1,101 @@
|
|||
-- Copyright (C) Yichun Zhang (agentzh)
|
||||
|
||||
|
||||
local ffi = require "ffi"
|
||||
local debug = require "debug"
|
||||
local base = require "resty.core.base"
|
||||
local misc = require "resty.core.misc"
|
||||
|
||||
|
||||
local C = ffi.C
|
||||
local register_getter = misc.register_ngx_magic_key_getter
|
||||
local register_setter = misc.register_ngx_magic_key_setter
|
||||
local registry = debug.getregistry()
|
||||
local new_tab = base.new_tab
|
||||
local ref_in_table = base.ref_in_table
|
||||
local get_request = base.get_request
|
||||
local FFI_NO_REQ_CTX = base.FFI_NO_REQ_CTX
|
||||
local FFI_OK = base.FFI_OK
|
||||
local error = error
|
||||
local subsystem = ngx.config.subsystem
|
||||
|
||||
|
||||
local ngx_lua_ffi_get_ctx_ref
|
||||
local ngx_lua_ffi_set_ctx_ref
|
||||
|
||||
|
||||
if subsystem == "http" then
|
||||
ffi.cdef[[
|
||||
int ngx_http_lua_ffi_get_ctx_ref(ngx_http_request_t *r);
|
||||
int ngx_http_lua_ffi_set_ctx_ref(ngx_http_request_t *r, int ref);
|
||||
]]
|
||||
|
||||
ngx_lua_ffi_get_ctx_ref = C.ngx_http_lua_ffi_get_ctx_ref
|
||||
ngx_lua_ffi_set_ctx_ref = C.ngx_http_lua_ffi_set_ctx_ref
|
||||
|
||||
elseif subsystem == "stream" then
|
||||
ffi.cdef[[
|
||||
int ngx_stream_lua_ffi_get_ctx_ref(ngx_stream_lua_request_t *r);
|
||||
int ngx_stream_lua_ffi_set_ctx_ref(ngx_stream_lua_request_t *r, int ref);
|
||||
]]
|
||||
|
||||
ngx_lua_ffi_get_ctx_ref = C.ngx_stream_lua_ffi_get_ctx_ref
|
||||
ngx_lua_ffi_set_ctx_ref = C.ngx_stream_lua_ffi_set_ctx_ref
|
||||
end
|
||||
|
||||
|
||||
local _M = {
|
||||
_VERSION = base.version
|
||||
}
|
||||
|
||||
|
||||
local function get_ctx_table()
|
||||
local r = get_request()
|
||||
|
||||
if not r then
|
||||
error("no request found")
|
||||
end
|
||||
|
||||
local ctx_ref = ngx_lua_ffi_get_ctx_ref(r)
|
||||
if ctx_ref == FFI_NO_REQ_CTX then
|
||||
error("no request ctx found")
|
||||
end
|
||||
|
||||
local ctxs = registry.ngx_lua_ctx_tables
|
||||
if ctx_ref < 0 then
|
||||
local ctx = new_tab(0, 4)
|
||||
ctx_ref = ref_in_table(ctxs, ctx)
|
||||
if ngx_lua_ffi_set_ctx_ref(r, ctx_ref) ~= FFI_OK then
|
||||
return nil
|
||||
end
|
||||
return ctx
|
||||
end
|
||||
return ctxs[ctx_ref]
|
||||
end
|
||||
register_getter("ctx", get_ctx_table)
|
||||
|
||||
|
||||
local function set_ctx_table(ctx)
|
||||
local r = get_request()
|
||||
|
||||
if not r then
|
||||
error("no request found")
|
||||
end
|
||||
|
||||
local ctx_ref = ngx_lua_ffi_get_ctx_ref(r)
|
||||
if ctx_ref == FFI_NO_REQ_CTX then
|
||||
error("no request ctx found")
|
||||
end
|
||||
|
||||
local ctxs = registry.ngx_lua_ctx_tables
|
||||
if ctx_ref < 0 then
|
||||
ctx_ref = ref_in_table(ctxs, ctx)
|
||||
ngx_lua_ffi_set_ctx_ref(r, ctx_ref)
|
||||
return
|
||||
end
|
||||
ctxs[ctx_ref] = ctx
|
||||
end
|
||||
register_setter("ctx", set_ctx_table)
|
||||
|
||||
|
||||
return _M
|
66
resty/core/exit.lua
Normal file
66
resty/core/exit.lua
Normal file
|
@ -0,0 +1,66 @@
|
|||
-- Copyright (C) Yichun Zhang (agentzh)
|
||||
|
||||
|
||||
local ffi = require "ffi"
|
||||
local base = require "resty.core.base"
|
||||
|
||||
|
||||
local C = ffi.C
|
||||
local ffi_string = ffi.string
|
||||
local ngx = ngx
|
||||
local error = error
|
||||
local get_string_buf = base.get_string_buf
|
||||
local get_size_ptr = base.get_size_ptr
|
||||
local get_request = base.get_request
|
||||
local co_yield = coroutine._yield
|
||||
local subsystem = ngx.config.subsystem
|
||||
|
||||
|
||||
local ngx_lua_ffi_exit
|
||||
|
||||
|
||||
if subsystem == "http" then
|
||||
ffi.cdef[[
|
||||
int ngx_http_lua_ffi_exit(ngx_http_request_t *r, int status,
|
||||
unsigned char *err, size_t *errlen);
|
||||
]]
|
||||
|
||||
ngx_lua_ffi_exit = C.ngx_http_lua_ffi_exit
|
||||
|
||||
elseif subsystem == "stream" then
|
||||
ffi.cdef[[
|
||||
int ngx_stream_lua_ffi_exit(ngx_stream_lua_request_t *r, int status,
|
||||
unsigned char *err, size_t *errlen);
|
||||
]]
|
||||
|
||||
ngx_lua_ffi_exit = C.ngx_stream_lua_ffi_exit
|
||||
end
|
||||
|
||||
|
||||
local ERR_BUF_SIZE = 128
|
||||
local FFI_DONE = base.FFI_DONE
|
||||
|
||||
|
||||
ngx.exit = function (rc)
|
||||
local err = get_string_buf(ERR_BUF_SIZE)
|
||||
local errlen = get_size_ptr()
|
||||
local r = get_request()
|
||||
if r == nil then
|
||||
error("no request found")
|
||||
end
|
||||
errlen[0] = ERR_BUF_SIZE
|
||||
rc = ngx_lua_ffi_exit(r, rc, err, errlen)
|
||||
if rc == 0 then
|
||||
-- print("yielding...")
|
||||
return co_yield()
|
||||
end
|
||||
if rc == FFI_DONE then
|
||||
return
|
||||
end
|
||||
error(ffi_string(err, errlen[0]), 2)
|
||||
end
|
||||
|
||||
|
||||
return {
|
||||
version = base.version
|
||||
}
|
110
resty/core/hash.lua
Normal file
110
resty/core/hash.lua
Normal file
|
@ -0,0 +1,110 @@
|
|||
-- Copyright (C) Yichun Zhang (agentzh)
|
||||
|
||||
|
||||
local ffi = require "ffi"
|
||||
local base = require "resty.core.base"
|
||||
|
||||
|
||||
local C = ffi.C
|
||||
local ffi_new = ffi.new
|
||||
local ffi_string = ffi.string
|
||||
local ngx = ngx
|
||||
local type = type
|
||||
local error = error
|
||||
local tostring = tostring
|
||||
local subsystem = ngx.config.subsystem
|
||||
|
||||
|
||||
local ngx_lua_ffi_md5
|
||||
local ngx_lua_ffi_md5_bin
|
||||
local ngx_lua_ffi_sha1_bin
|
||||
|
||||
|
||||
if subsystem == "http" then
|
||||
ffi.cdef[[
|
||||
void ngx_http_lua_ffi_md5_bin(const unsigned char *src, size_t len,
|
||||
unsigned char *dst);
|
||||
|
||||
void ngx_http_lua_ffi_md5(const unsigned char *src, size_t len,
|
||||
unsigned char *dst);
|
||||
|
||||
int ngx_http_lua_ffi_sha1_bin(const unsigned char *src, size_t len,
|
||||
unsigned char *dst);
|
||||
]]
|
||||
|
||||
ngx_lua_ffi_md5 = C.ngx_http_lua_ffi_md5
|
||||
ngx_lua_ffi_md5_bin = C.ngx_http_lua_ffi_md5_bin
|
||||
ngx_lua_ffi_sha1_bin = C.ngx_http_lua_ffi_sha1_bin
|
||||
|
||||
elseif subsystem == "stream" then
|
||||
ffi.cdef[[
|
||||
void ngx_stream_lua_ffi_md5_bin(const unsigned char *src, size_t len,
|
||||
unsigned char *dst);
|
||||
|
||||
void ngx_stream_lua_ffi_md5(const unsigned char *src, size_t len,
|
||||
unsigned char *dst);
|
||||
|
||||
int ngx_stream_lua_ffi_sha1_bin(const unsigned char *src, size_t len,
|
||||
unsigned char *dst);
|
||||
]]
|
||||
|
||||
ngx_lua_ffi_md5 = C.ngx_stream_lua_ffi_md5
|
||||
ngx_lua_ffi_md5_bin = C.ngx_stream_lua_ffi_md5_bin
|
||||
ngx_lua_ffi_sha1_bin = C.ngx_stream_lua_ffi_sha1_bin
|
||||
end
|
||||
|
||||
|
||||
local MD5_DIGEST_LEN = 16
|
||||
local md5_buf = ffi_new("unsigned char[?]", MD5_DIGEST_LEN)
|
||||
|
||||
ngx.md5_bin = function (s)
|
||||
if type(s) ~= 'string' then
|
||||
if not s then
|
||||
s = ''
|
||||
else
|
||||
s = tostring(s)
|
||||
end
|
||||
end
|
||||
ngx_lua_ffi_md5_bin(s, #s, md5_buf)
|
||||
return ffi_string(md5_buf, MD5_DIGEST_LEN)
|
||||
end
|
||||
|
||||
|
||||
local MD5_HEX_DIGEST_LEN = MD5_DIGEST_LEN * 2
|
||||
local md5_hex_buf = ffi_new("unsigned char[?]", MD5_HEX_DIGEST_LEN)
|
||||
|
||||
ngx.md5 = function (s)
|
||||
if type(s) ~= 'string' then
|
||||
if not s then
|
||||
s = ''
|
||||
else
|
||||
s = tostring(s)
|
||||
end
|
||||
end
|
||||
ngx_lua_ffi_md5(s, #s, md5_hex_buf)
|
||||
return ffi_string(md5_hex_buf, MD5_HEX_DIGEST_LEN)
|
||||
end
|
||||
|
||||
|
||||
local SHA_DIGEST_LEN = 20
|
||||
local sha_buf = ffi_new("unsigned char[?]", SHA_DIGEST_LEN)
|
||||
|
||||
ngx.sha1_bin = function (s)
|
||||
if type(s) ~= 'string' then
|
||||
if not s then
|
||||
s = ''
|
||||
else
|
||||
s = tostring(s)
|
||||
end
|
||||
end
|
||||
local ok = ngx_lua_ffi_sha1_bin(s, #s, sha_buf)
|
||||
if ok == 0 then
|
||||
error("SHA-1 support missing in Nginx")
|
||||
end
|
||||
return ffi_string(sha_buf, SHA_DIGEST_LEN)
|
||||
end
|
||||
|
||||
|
||||
return {
|
||||
version = base.version
|
||||
}
|
240
resty/core/misc.lua
Normal file
240
resty/core/misc.lua
Normal file
|
@ -0,0 +1,240 @@
|
|||
-- Copyright (C) Yichun Zhang (agentzh)
|
||||
|
||||
|
||||
local base = require "resty.core.base"
|
||||
local ffi = require "ffi"
|
||||
local os = require "os"
|
||||
|
||||
|
||||
local C = ffi.C
|
||||
local ffi_new = ffi.new
|
||||
local ffi_str = ffi.string
|
||||
local ngx = ngx
|
||||
local type = type
|
||||
local error = error
|
||||
local rawget = rawget
|
||||
local rawset = rawset
|
||||
local tonumber = tonumber
|
||||
local setmetatable = setmetatable
|
||||
local FFI_OK = base.FFI_OK
|
||||
local FFI_NO_REQ_CTX = base.FFI_NO_REQ_CTX
|
||||
local FFI_BAD_CONTEXT = base.FFI_BAD_CONTEXT
|
||||
local new_tab = base.new_tab
|
||||
local get_request = base.get_request
|
||||
local get_size_ptr = base.get_size_ptr
|
||||
local get_string_buf = base.get_string_buf
|
||||
local get_string_buf_size = base.get_string_buf_size
|
||||
local subsystem = ngx.config.subsystem
|
||||
|
||||
|
||||
local ngx_lua_ffi_get_resp_status
|
||||
local ngx_lua_ffi_get_conf_env
|
||||
local ngx_magic_key_getters
|
||||
local ngx_magic_key_setters
|
||||
|
||||
|
||||
local _M = new_tab(0, 3)
|
||||
local ngx_mt = new_tab(0, 2)
|
||||
|
||||
|
||||
if subsystem == "http" then
|
||||
ngx_magic_key_getters = new_tab(0, 4)
|
||||
ngx_magic_key_setters = new_tab(0, 2)
|
||||
|
||||
elseif subsystem == "stream" then
|
||||
ngx_magic_key_getters = new_tab(0, 2)
|
||||
ngx_magic_key_setters = new_tab(0, 1)
|
||||
end
|
||||
|
||||
|
||||
local function register_getter(key, func)
|
||||
ngx_magic_key_getters[key] = func
|
||||
end
|
||||
_M.register_ngx_magic_key_getter = register_getter
|
||||
|
||||
|
||||
local function register_setter(key, func)
|
||||
ngx_magic_key_setters[key] = func
|
||||
end
|
||||
_M.register_ngx_magic_key_setter = register_setter
|
||||
|
||||
|
||||
ngx_mt.__index = function (tb, key)
|
||||
local f = ngx_magic_key_getters[key]
|
||||
if f then
|
||||
return f()
|
||||
end
|
||||
return rawget(tb, key)
|
||||
end
|
||||
|
||||
|
||||
ngx_mt.__newindex = function (tb, key, ctx)
|
||||
local f = ngx_magic_key_setters[key]
|
||||
if f then
|
||||
return f(ctx)
|
||||
end
|
||||
return rawset(tb, key, ctx)
|
||||
end
|
||||
|
||||
|
||||
setmetatable(ngx, ngx_mt)
|
||||
|
||||
|
||||
if subsystem == "http" then
|
||||
ffi.cdef[[
|
||||
int ngx_http_lua_ffi_get_resp_status(ngx_http_request_t *r);
|
||||
int ngx_http_lua_ffi_set_resp_status(ngx_http_request_t *r, int r);
|
||||
int ngx_http_lua_ffi_is_subrequest(ngx_http_request_t *r);
|
||||
int ngx_http_lua_ffi_headers_sent(ngx_http_request_t *r);
|
||||
int ngx_http_lua_ffi_get_conf_env(const unsigned char *name,
|
||||
unsigned char **env_buf,
|
||||
size_t *name_len);
|
||||
]]
|
||||
|
||||
|
||||
ngx_lua_ffi_get_resp_status = C.ngx_http_lua_ffi_get_resp_status
|
||||
ngx_lua_ffi_get_conf_env = C.ngx_http_lua_ffi_get_conf_env
|
||||
|
||||
|
||||
-- ngx.status
|
||||
|
||||
|
||||
local function set_status(status)
|
||||
local r = get_request()
|
||||
|
||||
if not r then
|
||||
error("no request found")
|
||||
end
|
||||
|
||||
if type(status) ~= 'number' then
|
||||
status = tonumber(status)
|
||||
end
|
||||
|
||||
local rc = C.ngx_http_lua_ffi_set_resp_status(r, status)
|
||||
|
||||
if rc == FFI_BAD_CONTEXT then
|
||||
error("API disabled in the current context", 2)
|
||||
end
|
||||
|
||||
return
|
||||
end
|
||||
register_setter("status", set_status)
|
||||
|
||||
|
||||
-- ngx.is_subrequest
|
||||
|
||||
|
||||
local function is_subreq()
|
||||
local r = get_request()
|
||||
|
||||
if not r then
|
||||
error("no request found")
|
||||
end
|
||||
|
||||
local rc = C.ngx_http_lua_ffi_is_subrequest(r)
|
||||
|
||||
if rc == FFI_BAD_CONTEXT then
|
||||
error("API disabled in the current context", 2)
|
||||
end
|
||||
|
||||
return rc == 1
|
||||
end
|
||||
register_getter("is_subrequest", is_subreq)
|
||||
|
||||
|
||||
-- ngx.headers_sent
|
||||
|
||||
|
||||
local function headers_sent()
|
||||
local r = get_request()
|
||||
|
||||
if not r then
|
||||
error("no request found")
|
||||
end
|
||||
|
||||
local rc = C.ngx_http_lua_ffi_headers_sent(r)
|
||||
|
||||
if rc == FFI_NO_REQ_CTX then
|
||||
error("no request ctx found")
|
||||
end
|
||||
|
||||
if rc == FFI_BAD_CONTEXT then
|
||||
error("API disabled in the current context", 2)
|
||||
end
|
||||
|
||||
return rc == 1
|
||||
end
|
||||
register_getter("headers_sent", headers_sent)
|
||||
|
||||
elseif subsystem == "stream" then
|
||||
ffi.cdef[[
|
||||
int ngx_stream_lua_ffi_get_resp_status(ngx_stream_lua_request_t *r);
|
||||
int ngx_stream_lua_ffi_get_conf_env(const unsigned char *name,
|
||||
unsigned char **env_buf,
|
||||
size_t *name_len);
|
||||
]]
|
||||
|
||||
ngx_lua_ffi_get_resp_status = C.ngx_stream_lua_ffi_get_resp_status
|
||||
ngx_lua_ffi_get_conf_env = C.ngx_stream_lua_ffi_get_conf_env
|
||||
end
|
||||
|
||||
|
||||
-- ngx.status
|
||||
|
||||
|
||||
local function get_status()
|
||||
local r = get_request()
|
||||
|
||||
if not r then
|
||||
error("no request found")
|
||||
end
|
||||
|
||||
local rc = ngx_lua_ffi_get_resp_status(r)
|
||||
|
||||
if rc == FFI_BAD_CONTEXT then
|
||||
error("API disabled in the current context", 2)
|
||||
end
|
||||
|
||||
return rc
|
||||
end
|
||||
register_getter("status", get_status)
|
||||
|
||||
|
||||
do
|
||||
local _getenv = os.getenv
|
||||
local env_ptr = ffi_new("unsigned char *[1]")
|
||||
|
||||
os.getenv = function (name)
|
||||
local r = get_request()
|
||||
if r then
|
||||
-- past init_by_lua* phase now
|
||||
os.getenv = _getenv
|
||||
env_ptr = nil
|
||||
return os.getenv(name)
|
||||
end
|
||||
|
||||
local size = get_string_buf_size()
|
||||
env_ptr[0] = get_string_buf(size)
|
||||
local name_len_ptr = get_size_ptr()
|
||||
|
||||
local rc = ngx_lua_ffi_get_conf_env(name, env_ptr, name_len_ptr)
|
||||
if rc == FFI_OK then
|
||||
return ffi_str(env_ptr[0] + name_len_ptr[0] + 1)
|
||||
end
|
||||
|
||||
-- FFI_DECLINED
|
||||
|
||||
local value = _getenv(name)
|
||||
if value ~= nil then
|
||||
return value
|
||||
end
|
||||
|
||||
return nil
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
_M._VERSION = base.version
|
||||
|
||||
|
||||
return _M
|
92
resty/core/ndk.lua
Normal file
92
resty/core/ndk.lua
Normal file
|
@ -0,0 +1,92 @@
|
|||
-- Copyright (C) by OpenResty Inc.
|
||||
|
||||
|
||||
local ffi = require 'ffi'
|
||||
local base = require "resty.core.base"
|
||||
base.allows_subsystem('http')
|
||||
|
||||
|
||||
local C = ffi.C
|
||||
local ffi_cast = ffi.cast
|
||||
local ffi_new = ffi.new
|
||||
local ffi_str = ffi.string
|
||||
local FFI_OK = base.FFI_OK
|
||||
local new_tab = base.new_tab
|
||||
local get_string_buf = base.get_string_buf
|
||||
local get_request = base.get_request
|
||||
local setmetatable = setmetatable
|
||||
local type = type
|
||||
local tostring = tostring
|
||||
local error = error
|
||||
|
||||
|
||||
local _M = {
|
||||
version = base.version
|
||||
}
|
||||
|
||||
|
||||
ffi.cdef[[
|
||||
typedef void * ndk_set_var_value_pt;
|
||||
|
||||
int ngx_http_lua_ffi_ndk_lookup_directive(const unsigned char *var_data,
|
||||
size_t var_len, ndk_set_var_value_pt *func);
|
||||
int ngx_http_lua_ffi_ndk_set_var_get(ngx_http_request_t *r,
|
||||
ndk_set_var_value_pt func, const unsigned char *arg_data, size_t arg_len,
|
||||
ngx_http_lua_ffi_str_t *value);
|
||||
]]
|
||||
|
||||
|
||||
local func_p = ffi_new("void*[1]")
|
||||
local ffi_str_size = ffi.sizeof("ngx_http_lua_ffi_str_t")
|
||||
local ffi_str_type = ffi.typeof("ngx_http_lua_ffi_str_t*")
|
||||
|
||||
|
||||
local function ndk_set_var_get(self, var)
|
||||
if type(var) ~= "string" then
|
||||
var = tostring(var)
|
||||
end
|
||||
|
||||
if C.ngx_http_lua_ffi_ndk_lookup_directive(var, #var, func_p) ~= FFI_OK then
|
||||
error('ndk.set_var: directive "' .. var
|
||||
.. '" not found or does not use ndk_set_var_value', 2)
|
||||
end
|
||||
|
||||
local func = func_p[0]
|
||||
|
||||
return function (arg)
|
||||
local r = get_request()
|
||||
if not r then
|
||||
error("no request found")
|
||||
end
|
||||
|
||||
if type(arg) ~= "string" then
|
||||
arg = tostring(arg)
|
||||
end
|
||||
|
||||
local buf = get_string_buf(ffi_str_size)
|
||||
local value = ffi_cast(ffi_str_type, buf)
|
||||
local rc = C.ngx_http_lua_ffi_ndk_set_var_get(r, func, arg, #arg, value)
|
||||
if rc ~= FFI_OK then
|
||||
error("calling directive " .. var .. " failed with code " .. rc, 2)
|
||||
end
|
||||
|
||||
return ffi_str(value.data, value.len)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
local function ndk_set_var_set()
|
||||
error("not allowed", 2)
|
||||
end
|
||||
|
||||
|
||||
if ndk then
|
||||
local mt = new_tab(0, 2)
|
||||
mt.__newindex = ndk_set_var_set
|
||||
mt.__index = ndk_set_var_get
|
||||
|
||||
ndk.set_var = setmetatable(new_tab(0, 0), mt)
|
||||
end
|
||||
|
||||
|
||||
return _M
|
58
resty/core/phase.lua
Normal file
58
resty/core/phase.lua
Normal file
|
@ -0,0 +1,58 @@
|
|||
local ffi = require 'ffi'
|
||||
local base = require "resty.core.base"
|
||||
|
||||
local C = ffi.C
|
||||
local FFI_ERROR = base.FFI_ERROR
|
||||
local get_request = base.get_request
|
||||
local error = error
|
||||
local tostring = tostring
|
||||
|
||||
|
||||
ffi.cdef[[
|
||||
int ngx_http_lua_ffi_get_phase(ngx_http_request_t *r, char **err)
|
||||
]]
|
||||
|
||||
|
||||
local errmsg = base.get_errmsg_ptr()
|
||||
local context_names = {
|
||||
[0x0001] = "set",
|
||||
[0x0002] = "rewrite",
|
||||
[0x0004] = "access",
|
||||
[0x0008] = "content",
|
||||
[0x0010] = "log",
|
||||
[0x0020] = "header_filter",
|
||||
[0x0040] = "body_filter",
|
||||
[0x0080] = "timer",
|
||||
[0x0100] = "init_worker",
|
||||
[0x0200] = "balancer",
|
||||
[0x0400] = "ssl_cert",
|
||||
[0x0800] = "ssl_session_store",
|
||||
[0x1000] = "ssl_session_fetch",
|
||||
}
|
||||
|
||||
|
||||
function ngx.get_phase()
|
||||
local r = get_request()
|
||||
|
||||
-- if we have no request object, assume we are called from the "init" phase
|
||||
if not r then
|
||||
return "init"
|
||||
end
|
||||
|
||||
local context = C.ngx_http_lua_ffi_get_phase(r, errmsg)
|
||||
if context == FFI_ERROR then -- NGX_ERROR
|
||||
error(errmsg, 2)
|
||||
end
|
||||
|
||||
local phase = context_names[context]
|
||||
if not phase then
|
||||
error("unknown phase: " .. tostring(context))
|
||||
end
|
||||
|
||||
return phase
|
||||
end
|
||||
|
||||
|
||||
return {
|
||||
version = base.version
|
||||
}
|
1195
resty/core/regex.lua
Normal file
1195
resty/core/regex.lua
Normal file
File diff suppressed because it is too large
Load diff
367
resty/core/request.lua
Normal file
367
resty/core/request.lua
Normal file
|
@ -0,0 +1,367 @@
|
|||
-- Copyright (C) Yichun Zhang (agentzh)
|
||||
|
||||
|
||||
local ffi = require 'ffi'
|
||||
local base = require "resty.core.base"
|
||||
base.allows_subsystem("http")
|
||||
local utils = require "resty.core.utils"
|
||||
|
||||
|
||||
local FFI_BAD_CONTEXT = base.FFI_BAD_CONTEXT
|
||||
local FFI_DECLINED = base.FFI_DECLINED
|
||||
local FFI_OK = base.FFI_OK
|
||||
local new_tab = base.new_tab
|
||||
local C = ffi.C
|
||||
local ffi_cast = ffi.cast
|
||||
local ffi_new = ffi.new
|
||||
local ffi_str = ffi.string
|
||||
local get_string_buf = base.get_string_buf
|
||||
local get_size_ptr = base.get_size_ptr
|
||||
local setmetatable = setmetatable
|
||||
local lower = string.lower
|
||||
local rawget = rawget
|
||||
local ngx = ngx
|
||||
local get_request = base.get_request
|
||||
local type = type
|
||||
local error = error
|
||||
local tostring = tostring
|
||||
local tonumber = tonumber
|
||||
local str_replace_char = utils.str_replace_char
|
||||
|
||||
|
||||
ffi.cdef[[
|
||||
typedef struct {
|
||||
ngx_http_lua_ffi_str_t key;
|
||||
ngx_http_lua_ffi_str_t value;
|
||||
} ngx_http_lua_ffi_table_elt_t;
|
||||
|
||||
int ngx_http_lua_ffi_req_get_headers_count(ngx_http_request_t *r,
|
||||
int max, int *truncated);
|
||||
|
||||
int ngx_http_lua_ffi_req_get_headers(ngx_http_request_t *r,
|
||||
ngx_http_lua_ffi_table_elt_t *out, int count, int raw);
|
||||
|
||||
int ngx_http_lua_ffi_req_get_uri_args_count(ngx_http_request_t *r,
|
||||
int max, int *truncated);
|
||||
|
||||
size_t ngx_http_lua_ffi_req_get_querystring_len(ngx_http_request_t *r);
|
||||
|
||||
int ngx_http_lua_ffi_req_get_uri_args(ngx_http_request_t *r,
|
||||
unsigned char *buf, ngx_http_lua_ffi_table_elt_t *out, int count);
|
||||
|
||||
double ngx_http_lua_ffi_req_start_time(ngx_http_request_t *r);
|
||||
|
||||
int ngx_http_lua_ffi_req_get_method(ngx_http_request_t *r);
|
||||
|
||||
int ngx_http_lua_ffi_req_get_method_name(ngx_http_request_t *r,
|
||||
unsigned char **name, size_t *len);
|
||||
|
||||
int ngx_http_lua_ffi_req_set_method(ngx_http_request_t *r, int method);
|
||||
|
||||
int ngx_http_lua_ffi_req_header_set_single_value(ngx_http_request_t *r,
|
||||
const unsigned char *key, size_t key_len, const unsigned char *value,
|
||||
size_t value_len);
|
||||
]]
|
||||
|
||||
|
||||
local table_elt_type = ffi.typeof("ngx_http_lua_ffi_table_elt_t*")
|
||||
local table_elt_size = ffi.sizeof("ngx_http_lua_ffi_table_elt_t")
|
||||
local truncated = ffi.new("int[1]")
|
||||
|
||||
local req_headers_mt = {
|
||||
__index = function (tb, key)
|
||||
return rawget(tb, (str_replace_char(lower(key), '_', '-')))
|
||||
end
|
||||
}
|
||||
|
||||
|
||||
function ngx.req.get_headers(max_headers, raw)
|
||||
local r = get_request()
|
||||
if not r then
|
||||
error("no request found")
|
||||
end
|
||||
|
||||
if not max_headers then
|
||||
max_headers = -1
|
||||
end
|
||||
|
||||
if not raw then
|
||||
raw = 0
|
||||
else
|
||||
raw = 1
|
||||
end
|
||||
|
||||
local n = C.ngx_http_lua_ffi_req_get_headers_count(r, max_headers,
|
||||
truncated)
|
||||
if n == FFI_BAD_CONTEXT then
|
||||
error("API disabled in the current context", 2)
|
||||
end
|
||||
|
||||
if n == 0 then
|
||||
return {}
|
||||
end
|
||||
|
||||
local raw_buf = get_string_buf(n * table_elt_size)
|
||||
local buf = ffi_cast(table_elt_type, raw_buf)
|
||||
|
||||
local rc = C.ngx_http_lua_ffi_req_get_headers(r, buf, n, raw)
|
||||
if rc == 0 then
|
||||
local headers = new_tab(0, n)
|
||||
for i = 0, n - 1 do
|
||||
local h = buf[i]
|
||||
|
||||
local key = h.key
|
||||
key = ffi_str(key.data, key.len)
|
||||
|
||||
local value = h.value
|
||||
value = ffi_str(value.data, value.len)
|
||||
|
||||
local existing = headers[key]
|
||||
if existing then
|
||||
if type(existing) == "table" then
|
||||
existing[#existing + 1] = value
|
||||
else
|
||||
headers[key] = {existing, value}
|
||||
end
|
||||
|
||||
else
|
||||
headers[key] = value
|
||||
end
|
||||
end
|
||||
|
||||
if raw == 0 then
|
||||
headers = setmetatable(headers, req_headers_mt)
|
||||
end
|
||||
|
||||
if truncated[0] ~= 0 then
|
||||
return headers, "truncated"
|
||||
end
|
||||
|
||||
return headers
|
||||
end
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
|
||||
function ngx.req.get_uri_args(max_args)
|
||||
local r = get_request()
|
||||
if not r then
|
||||
error("no request found")
|
||||
end
|
||||
|
||||
if not max_args then
|
||||
max_args = -1
|
||||
end
|
||||
|
||||
local n = C.ngx_http_lua_ffi_req_get_uri_args_count(r, max_args, truncated)
|
||||
if n == FFI_BAD_CONTEXT then
|
||||
error("API disabled in the current context", 2)
|
||||
end
|
||||
|
||||
if n == 0 then
|
||||
return {}
|
||||
end
|
||||
|
||||
local args_len = C.ngx_http_lua_ffi_req_get_querystring_len(r)
|
||||
|
||||
local strbuf = get_string_buf(args_len + n * table_elt_size)
|
||||
local kvbuf = ffi_cast(table_elt_type, strbuf + args_len)
|
||||
|
||||
local nargs = C.ngx_http_lua_ffi_req_get_uri_args(r, strbuf, kvbuf, n)
|
||||
|
||||
local args = new_tab(0, nargs)
|
||||
for i = 0, nargs - 1 do
|
||||
local arg = kvbuf[i]
|
||||
|
||||
local key = arg.key
|
||||
key = ffi_str(key.data, key.len)
|
||||
|
||||
local value = arg.value
|
||||
local len = value.len
|
||||
if len == -1 then
|
||||
value = true
|
||||
else
|
||||
value = ffi_str(value.data, len)
|
||||
end
|
||||
|
||||
local existing = args[key]
|
||||
if existing then
|
||||
if type(existing) == "table" then
|
||||
existing[#existing + 1] = value
|
||||
else
|
||||
args[key] = {existing, value}
|
||||
end
|
||||
|
||||
else
|
||||
args[key] = value
|
||||
end
|
||||
end
|
||||
|
||||
if truncated[0] ~= 0 then
|
||||
return args, "truncated"
|
||||
end
|
||||
|
||||
return args
|
||||
end
|
||||
|
||||
|
||||
function ngx.req.start_time()
|
||||
local r = get_request()
|
||||
if not r then
|
||||
error("no request found")
|
||||
end
|
||||
|
||||
return tonumber(C.ngx_http_lua_ffi_req_start_time(r))
|
||||
end
|
||||
|
||||
|
||||
do
|
||||
local methods = {
|
||||
[0x0002] = "GET",
|
||||
[0x0004] = "HEAD",
|
||||
[0x0008] = "POST",
|
||||
[0x0010] = "PUT",
|
||||
[0x0020] = "DELETE",
|
||||
[0x0040] = "MKCOL",
|
||||
[0x0080] = "COPY",
|
||||
[0x0100] = "MOVE",
|
||||
[0x0200] = "OPTIONS",
|
||||
[0x0400] = "PROPFIND",
|
||||
[0x0800] = "PROPPATCH",
|
||||
[0x1000] = "LOCK",
|
||||
[0x2000] = "UNLOCK",
|
||||
[0x4000] = "PATCH",
|
||||
[0x8000] = "TRACE",
|
||||
}
|
||||
|
||||
local namep = ffi_new("unsigned char *[1]")
|
||||
|
||||
function ngx.req.get_method()
|
||||
local r = get_request()
|
||||
if not r then
|
||||
error("no request found")
|
||||
end
|
||||
|
||||
do
|
||||
local id = C.ngx_http_lua_ffi_req_get_method(r)
|
||||
if id == FFI_BAD_CONTEXT then
|
||||
error("API disabled in the current context", 2)
|
||||
end
|
||||
|
||||
local method = methods[id]
|
||||
if method then
|
||||
return method
|
||||
end
|
||||
end
|
||||
|
||||
local sizep = get_size_ptr()
|
||||
local rc = C.ngx_http_lua_ffi_req_get_method_name(r, namep, sizep)
|
||||
if rc ~= 0 then
|
||||
return nil
|
||||
end
|
||||
|
||||
return ffi_str(namep[0], sizep[0])
|
||||
end
|
||||
end -- do
|
||||
|
||||
|
||||
function ngx.req.set_method(method)
|
||||
local r = get_request()
|
||||
if not r then
|
||||
error("no request found")
|
||||
end
|
||||
|
||||
if type(method) ~= "number" then
|
||||
error("bad method number", 2)
|
||||
end
|
||||
|
||||
local rc = C.ngx_http_lua_ffi_req_set_method(r, method)
|
||||
if rc == FFI_OK then
|
||||
return
|
||||
end
|
||||
|
||||
if rc == FFI_BAD_CONTEXT then
|
||||
error("API disabled in the current context", 2)
|
||||
end
|
||||
|
||||
if rc == FFI_DECLINED then
|
||||
error("unsupported HTTP method: " .. method, 2)
|
||||
end
|
||||
|
||||
error("unknown error: " .. rc)
|
||||
end
|
||||
|
||||
|
||||
do
|
||||
local orig_func = ngx.req.set_header
|
||||
|
||||
function ngx.req.set_header(name, value)
|
||||
if type(value) == "table" then
|
||||
return orig_func(name, value)
|
||||
end
|
||||
|
||||
local r = get_request()
|
||||
if not r then
|
||||
error("no request found")
|
||||
end
|
||||
|
||||
if type(name) ~= "string" then
|
||||
name = tostring(name)
|
||||
end
|
||||
|
||||
local rc
|
||||
if not value then
|
||||
rc = C.ngx_http_lua_ffi_req_header_set_single_value(r, name,
|
||||
#name, nil, 0)
|
||||
|
||||
else
|
||||
if type(value) ~= "string" then
|
||||
value = tostring(value)
|
||||
end
|
||||
|
||||
rc = C.ngx_http_lua_ffi_req_header_set_single_value(r, name,
|
||||
#name, value, #value)
|
||||
end
|
||||
|
||||
if rc == FFI_OK or rc == FFI_DECLINED then
|
||||
return
|
||||
end
|
||||
|
||||
if rc == FFI_BAD_CONTEXT then
|
||||
error("API disabled in the current context", 2)
|
||||
end
|
||||
|
||||
error("error")
|
||||
end
|
||||
end -- do
|
||||
|
||||
|
||||
function ngx.req.clear_header(name)
|
||||
local r = get_request()
|
||||
if not r then
|
||||
error("no request found")
|
||||
end
|
||||
|
||||
if type(name) ~= "string" then
|
||||
name = tostring(name)
|
||||
end
|
||||
|
||||
local rc = C.ngx_http_lua_ffi_req_header_set_single_value(r, name, #name,
|
||||
nil, 0)
|
||||
|
||||
if rc == FFI_OK or rc == FFI_DECLINED then
|
||||
return
|
||||
end
|
||||
|
||||
if rc == FFI_BAD_CONTEXT then
|
||||
error("API disabled in the current context", 2)
|
||||
end
|
||||
|
||||
error("error")
|
||||
end
|
||||
|
||||
|
||||
return {
|
||||
version = base.version
|
||||
}
|
183
resty/core/response.lua
Normal file
183
resty/core/response.lua
Normal file
|
@ -0,0 +1,183 @@
|
|||
-- Copyright (C) Yichun Zhang (agentzh)
|
||||
|
||||
|
||||
local ffi = require 'ffi'
|
||||
local base = require "resty.core.base"
|
||||
|
||||
|
||||
local C = ffi.C
|
||||
local ffi_cast = ffi.cast
|
||||
local ffi_str = ffi.string
|
||||
local new_tab = base.new_tab
|
||||
local FFI_BAD_CONTEXT = base.FFI_BAD_CONTEXT
|
||||
local FFI_NO_REQ_CTX = base.FFI_NO_REQ_CTX
|
||||
local FFI_DECLINED = base.FFI_DECLINED
|
||||
local get_string_buf = base.get_string_buf
|
||||
local setmetatable = setmetatable
|
||||
local type = type
|
||||
local tostring = tostring
|
||||
local get_request = base.get_request
|
||||
local error = error
|
||||
local ngx = ngx
|
||||
|
||||
|
||||
local _M = {
|
||||
version = base.version
|
||||
}
|
||||
|
||||
|
||||
local MAX_HEADER_VALUES = 100
|
||||
local errmsg = base.get_errmsg_ptr()
|
||||
local ffi_str_type = ffi.typeof("ngx_http_lua_ffi_str_t*")
|
||||
local ffi_str_size = ffi.sizeof("ngx_http_lua_ffi_str_t")
|
||||
|
||||
|
||||
ffi.cdef[[
|
||||
int ngx_http_lua_ffi_set_resp_header(ngx_http_request_t *r,
|
||||
const char *key_data, size_t key_len, int is_nil,
|
||||
const char *sval, size_t sval_len, ngx_http_lua_ffi_str_t *mvals,
|
||||
size_t mvals_len, int override, char **errmsg);
|
||||
|
||||
int ngx_http_lua_ffi_get_resp_header(ngx_http_request_t *r,
|
||||
const unsigned char *key, size_t key_len,
|
||||
unsigned char *key_buf, ngx_http_lua_ffi_str_t *values,
|
||||
int max_nvalues, char **errmsg);
|
||||
]]
|
||||
|
||||
|
||||
local function set_resp_header(tb, key, value, no_override)
|
||||
local r = get_request()
|
||||
if not r then
|
||||
error("no request found")
|
||||
end
|
||||
|
||||
if type(key) ~= "string" then
|
||||
key = tostring(key)
|
||||
end
|
||||
|
||||
local rc
|
||||
if value == nil then
|
||||
if no_override then
|
||||
error("invalid header value", 3)
|
||||
end
|
||||
|
||||
rc = C.ngx_http_lua_ffi_set_resp_header(r, key, #key, true, nil, 0, nil,
|
||||
0, 1, errmsg)
|
||||
else
|
||||
local sval, sval_len, mvals, mvals_len, buf
|
||||
|
||||
if type(value) == "table" then
|
||||
mvals_len = #value
|
||||
if mvals_len == 0 and no_override then
|
||||
return
|
||||
end
|
||||
|
||||
buf = get_string_buf(ffi_str_size * mvals_len)
|
||||
mvals = ffi_cast(ffi_str_type, buf)
|
||||
for i = 1, mvals_len do
|
||||
local s = value[i]
|
||||
if type(s) ~= "string" then
|
||||
s = tostring(s)
|
||||
value[i] = s
|
||||
end
|
||||
local str = mvals[i - 1]
|
||||
str.data = s
|
||||
str.len = #s
|
||||
end
|
||||
|
||||
sval_len = 0
|
||||
|
||||
else
|
||||
if type(value) ~= "string" then
|
||||
sval = tostring(value)
|
||||
else
|
||||
sval = value
|
||||
end
|
||||
sval_len = #sval
|
||||
|
||||
mvals_len = 0
|
||||
end
|
||||
|
||||
local override_int = no_override and 0 or 1
|
||||
rc = C.ngx_http_lua_ffi_set_resp_header(r, key, #key, false, sval,
|
||||
sval_len, mvals, mvals_len,
|
||||
override_int, errmsg)
|
||||
end
|
||||
|
||||
if rc == 0 or rc == FFI_DECLINED then
|
||||
return
|
||||
end
|
||||
|
||||
if rc == FFI_NO_REQ_CTX then
|
||||
error("no request ctx found")
|
||||
end
|
||||
|
||||
if rc == FFI_BAD_CONTEXT then
|
||||
error("API disabled in the current context", 2)
|
||||
end
|
||||
|
||||
-- rc == FFI_ERROR
|
||||
error(ffi_str(errmsg[0]), 2)
|
||||
end
|
||||
|
||||
|
||||
_M.set_resp_header = set_resp_header
|
||||
|
||||
|
||||
local function get_resp_header(tb, key)
|
||||
local r = get_request()
|
||||
if not r then
|
||||
error("no request found")
|
||||
end
|
||||
|
||||
if type(key) ~= "string" then
|
||||
key = tostring(key)
|
||||
end
|
||||
|
||||
local key_len = #key
|
||||
|
||||
local key_buf = get_string_buf(key_len + ffi_str_size * MAX_HEADER_VALUES)
|
||||
local values = ffi_cast(ffi_str_type, key_buf + key_len)
|
||||
local n = C.ngx_http_lua_ffi_get_resp_header(r, key, key_len, key_buf,
|
||||
values, MAX_HEADER_VALUES,
|
||||
errmsg)
|
||||
|
||||
-- print("retval: ", n)
|
||||
|
||||
if n == FFI_BAD_CONTEXT then
|
||||
error("API disabled in the current context", 2)
|
||||
end
|
||||
|
||||
if n == 0 then
|
||||
return nil
|
||||
end
|
||||
|
||||
if n == 1 then
|
||||
local v = values[0]
|
||||
return ffi_str(v.data, v.len)
|
||||
end
|
||||
|
||||
if n > 0 then
|
||||
local ret = new_tab(n, 0)
|
||||
for i = 1, n do
|
||||
local v = values[i - 1]
|
||||
ret[i] = ffi_str(v.data, v.len)
|
||||
end
|
||||
return ret
|
||||
end
|
||||
|
||||
-- n == FFI_ERROR
|
||||
error(ffi_str(errmsg[0]), 2)
|
||||
end
|
||||
|
||||
|
||||
do
|
||||
local mt = new_tab(0, 2)
|
||||
mt.__newindex = set_resp_header
|
||||
mt.__index = get_resp_header
|
||||
|
||||
ngx.header = setmetatable(new_tab(0, 0), mt)
|
||||
end
|
||||
|
||||
|
||||
return _M
|
638
resty/core/shdict.lua
Normal file
638
resty/core/shdict.lua
Normal file
|
@ -0,0 +1,638 @@
|
|||
-- Copyright (C) Yichun Zhang (agentzh)
|
||||
|
||||
|
||||
local ffi = require 'ffi'
|
||||
local base = require "resty.core.base"
|
||||
|
||||
|
||||
local _M = {
|
||||
version = base.version
|
||||
}
|
||||
|
||||
local ngx_shared = ngx.shared
|
||||
if not ngx_shared then
|
||||
return _M
|
||||
end
|
||||
|
||||
|
||||
local ffi_new = ffi.new
|
||||
local ffi_str = ffi.string
|
||||
local C = ffi.C
|
||||
local get_string_buf = base.get_string_buf
|
||||
local get_string_buf_size = base.get_string_buf_size
|
||||
local get_size_ptr = base.get_size_ptr
|
||||
local tonumber = tonumber
|
||||
local tostring = tostring
|
||||
local next = next
|
||||
local type = type
|
||||
local error = error
|
||||
local getmetatable = getmetatable
|
||||
local FFI_DECLINED = base.FFI_DECLINED
|
||||
local subsystem = ngx.config.subsystem
|
||||
|
||||
|
||||
local ngx_lua_ffi_shdict_get
|
||||
local ngx_lua_ffi_shdict_incr
|
||||
local ngx_lua_ffi_shdict_store
|
||||
local ngx_lua_ffi_shdict_flush_all
|
||||
local ngx_lua_ffi_shdict_get_ttl
|
||||
local ngx_lua_ffi_shdict_set_expire
|
||||
local ngx_lua_ffi_shdict_capacity
|
||||
local ngx_lua_ffi_shdict_free_space
|
||||
local ngx_lua_ffi_shdict_udata_to_zone
|
||||
|
||||
|
||||
if subsystem == 'http' then
|
||||
ffi.cdef[[
|
||||
int ngx_http_lua_ffi_shdict_get(void *zone, const unsigned char *key,
|
||||
size_t key_len, int *value_type, unsigned char **str_value_buf,
|
||||
size_t *str_value_len, double *num_value, int *user_flags,
|
||||
int get_stale, int *is_stale, char **errmsg);
|
||||
|
||||
int ngx_http_lua_ffi_shdict_incr(void *zone, const unsigned char *key,
|
||||
size_t key_len, double *value, char **err, int has_init,
|
||||
double init, long init_ttl, int *forcible);
|
||||
|
||||
int ngx_http_lua_ffi_shdict_store(void *zone, int op,
|
||||
const unsigned char *key, size_t key_len, int value_type,
|
||||
const unsigned char *str_value_buf, size_t str_value_len,
|
||||
double num_value, long exptime, int user_flags, char **errmsg,
|
||||
int *forcible);
|
||||
|
||||
int ngx_http_lua_ffi_shdict_flush_all(void *zone);
|
||||
|
||||
long ngx_http_lua_ffi_shdict_get_ttl(void *zone,
|
||||
const unsigned char *key, size_t key_len);
|
||||
|
||||
int ngx_http_lua_ffi_shdict_set_expire(void *zone,
|
||||
const unsigned char *key, size_t key_len, long exptime);
|
||||
|
||||
size_t ngx_http_lua_ffi_shdict_capacity(void *zone);
|
||||
|
||||
void *ngx_http_lua_ffi_shdict_udata_to_zone(void *zone_udata);
|
||||
]]
|
||||
|
||||
ngx_lua_ffi_shdict_get = C.ngx_http_lua_ffi_shdict_get
|
||||
ngx_lua_ffi_shdict_incr = C.ngx_http_lua_ffi_shdict_incr
|
||||
ngx_lua_ffi_shdict_store = C.ngx_http_lua_ffi_shdict_store
|
||||
ngx_lua_ffi_shdict_flush_all = C.ngx_http_lua_ffi_shdict_flush_all
|
||||
ngx_lua_ffi_shdict_get_ttl = C.ngx_http_lua_ffi_shdict_get_ttl
|
||||
ngx_lua_ffi_shdict_set_expire = C.ngx_http_lua_ffi_shdict_set_expire
|
||||
ngx_lua_ffi_shdict_capacity = C.ngx_http_lua_ffi_shdict_capacity
|
||||
ngx_lua_ffi_shdict_udata_to_zone =
|
||||
C.ngx_http_lua_ffi_shdict_udata_to_zone
|
||||
|
||||
if not pcall(function ()
|
||||
return C.ngx_http_lua_ffi_shdict_free_space
|
||||
end)
|
||||
then
|
||||
ffi.cdef[[
|
||||
size_t ngx_http_lua_ffi_shdict_free_space(void *zone);
|
||||
]]
|
||||
end
|
||||
|
||||
pcall(function ()
|
||||
ngx_lua_ffi_shdict_free_space = C.ngx_http_lua_ffi_shdict_free_space
|
||||
end)
|
||||
|
||||
elseif subsystem == 'stream' then
|
||||
|
||||
ffi.cdef[[
|
||||
int ngx_stream_lua_ffi_shdict_get(void *zone, const unsigned char *key,
|
||||
size_t key_len, int *value_type, unsigned char **str_value_buf,
|
||||
size_t *str_value_len, double *num_value, int *user_flags,
|
||||
int get_stale, int *is_stale, char **errmsg);
|
||||
|
||||
int ngx_stream_lua_ffi_shdict_incr(void *zone, const unsigned char *key,
|
||||
size_t key_len, double *value, char **err, int has_init,
|
||||
double init, long init_ttl, int *forcible);
|
||||
|
||||
int ngx_stream_lua_ffi_shdict_store(void *zone, int op,
|
||||
const unsigned char *key, size_t key_len, int value_type,
|
||||
const unsigned char *str_value_buf, size_t str_value_len,
|
||||
double num_value, long exptime, int user_flags, char **errmsg,
|
||||
int *forcible);
|
||||
|
||||
int ngx_stream_lua_ffi_shdict_flush_all(void *zone);
|
||||
|
||||
long ngx_stream_lua_ffi_shdict_get_ttl(void *zone,
|
||||
const unsigned char *key, size_t key_len);
|
||||
|
||||
int ngx_stream_lua_ffi_shdict_set_expire(void *zone,
|
||||
const unsigned char *key, size_t key_len, long exptime);
|
||||
|
||||
size_t ngx_stream_lua_ffi_shdict_capacity(void *zone);
|
||||
|
||||
void *ngx_stream_lua_ffi_shdict_udata_to_zone(void *zone_udata);
|
||||
]]
|
||||
|
||||
ngx_lua_ffi_shdict_get = C.ngx_stream_lua_ffi_shdict_get
|
||||
ngx_lua_ffi_shdict_incr = C.ngx_stream_lua_ffi_shdict_incr
|
||||
ngx_lua_ffi_shdict_store = C.ngx_stream_lua_ffi_shdict_store
|
||||
ngx_lua_ffi_shdict_flush_all = C.ngx_stream_lua_ffi_shdict_flush_all
|
||||
ngx_lua_ffi_shdict_get_ttl = C.ngx_stream_lua_ffi_shdict_get_ttl
|
||||
ngx_lua_ffi_shdict_set_expire = C.ngx_stream_lua_ffi_shdict_set_expire
|
||||
ngx_lua_ffi_shdict_capacity = C.ngx_stream_lua_ffi_shdict_capacity
|
||||
ngx_lua_ffi_shdict_udata_to_zone =
|
||||
C.ngx_stream_lua_ffi_shdict_udata_to_zone
|
||||
|
||||
if not pcall(function ()
|
||||
return C.ngx_stream_lua_ffi_shdict_free_space
|
||||
end)
|
||||
then
|
||||
ffi.cdef[[
|
||||
size_t ngx_stream_lua_ffi_shdict_free_space(void *zone);
|
||||
]]
|
||||
end
|
||||
|
||||
-- ngx_stream_lua is only compatible with NGINX >= 1.13.6, meaning it
|
||||
-- cannot lack support for ngx_stream_lua_ffi_shdict_free_space.
|
||||
ngx_lua_ffi_shdict_free_space = C.ngx_stream_lua_ffi_shdict_free_space
|
||||
|
||||
else
|
||||
error("unknown subsystem: " .. subsystem)
|
||||
end
|
||||
|
||||
if not pcall(function () return C.free end) then
|
||||
ffi.cdef[[
|
||||
void free(void *ptr);
|
||||
]]
|
||||
end
|
||||
|
||||
|
||||
local value_type = ffi_new("int[1]")
|
||||
local user_flags = ffi_new("int[1]")
|
||||
local num_value = ffi_new("double[1]")
|
||||
local is_stale = ffi_new("int[1]")
|
||||
local forcible = ffi_new("int[1]")
|
||||
local str_value_buf = ffi_new("unsigned char *[1]")
|
||||
local errmsg = base.get_errmsg_ptr()
|
||||
|
||||
|
||||
local function check_zone(zone)
|
||||
if not zone or type(zone) ~= "table" then
|
||||
error("bad \"zone\" argument", 3)
|
||||
end
|
||||
|
||||
zone = zone[1]
|
||||
if type(zone) ~= "userdata" then
|
||||
error("bad \"zone\" argument", 3)
|
||||
end
|
||||
|
||||
zone = ngx_lua_ffi_shdict_udata_to_zone(zone)
|
||||
if zone == nil then
|
||||
error("bad \"zone\" argument", 3)
|
||||
end
|
||||
|
||||
return zone
|
||||
end
|
||||
|
||||
|
||||
local function shdict_store(zone, op, key, value, exptime, flags)
|
||||
zone = check_zone(zone)
|
||||
|
||||
if not exptime then
|
||||
exptime = 0
|
||||
elseif exptime < 0 then
|
||||
error('bad "exptime" argument', 2)
|
||||
end
|
||||
|
||||
if not flags then
|
||||
flags = 0
|
||||
end
|
||||
|
||||
if key == nil then
|
||||
return nil, "nil key"
|
||||
end
|
||||
|
||||
if type(key) ~= "string" then
|
||||
key = tostring(key)
|
||||
end
|
||||
|
||||
local key_len = #key
|
||||
if key_len == 0 then
|
||||
return nil, "empty key"
|
||||
end
|
||||
if key_len > 65535 then
|
||||
return nil, "key too long"
|
||||
end
|
||||
|
||||
local str_val_buf
|
||||
local str_val_len = 0
|
||||
local num_val = 0
|
||||
local valtyp = type(value)
|
||||
|
||||
-- print("value type: ", valtyp)
|
||||
-- print("exptime: ", exptime)
|
||||
|
||||
if valtyp == "string" then
|
||||
valtyp = 4 -- LUA_TSTRING
|
||||
str_val_buf = value
|
||||
str_val_len = #value
|
||||
|
||||
elseif valtyp == "number" then
|
||||
valtyp = 3 -- LUA_TNUMBER
|
||||
num_val = value
|
||||
|
||||
elseif value == nil then
|
||||
valtyp = 0 -- LUA_TNIL
|
||||
|
||||
elseif valtyp == "boolean" then
|
||||
valtyp = 1 -- LUA_TBOOLEAN
|
||||
num_val = value and 1 or 0
|
||||
|
||||
else
|
||||
return nil, "bad value type"
|
||||
end
|
||||
|
||||
local rc = ngx_lua_ffi_shdict_store(zone, op, key, key_len,
|
||||
valtyp, str_val_buf,
|
||||
str_val_len, num_val,
|
||||
exptime * 1000, flags, errmsg,
|
||||
forcible)
|
||||
|
||||
-- print("rc == ", rc)
|
||||
|
||||
if rc == 0 then -- NGX_OK
|
||||
return true, nil, forcible[0] == 1
|
||||
end
|
||||
|
||||
-- NGX_DECLINED or NGX_ERROR
|
||||
return false, ffi_str(errmsg[0]), forcible[0] == 1
|
||||
end
|
||||
|
||||
|
||||
local function shdict_set(zone, key, value, exptime, flags)
|
||||
return shdict_store(zone, 0, key, value, exptime, flags)
|
||||
end
|
||||
|
||||
|
||||
local function shdict_safe_set(zone, key, value, exptime, flags)
|
||||
return shdict_store(zone, 0x0004, key, value, exptime, flags)
|
||||
end
|
||||
|
||||
|
||||
local function shdict_add(zone, key, value, exptime, flags)
|
||||
return shdict_store(zone, 0x0001, key, value, exptime, flags)
|
||||
end
|
||||
|
||||
|
||||
local function shdict_safe_add(zone, key, value, exptime, flags)
|
||||
return shdict_store(zone, 0x0005, key, value, exptime, flags)
|
||||
end
|
||||
|
||||
|
||||
local function shdict_replace(zone, key, value, exptime, flags)
|
||||
return shdict_store(zone, 0x0002, key, value, exptime, flags)
|
||||
end
|
||||
|
||||
|
||||
local function shdict_delete(zone, key)
|
||||
return shdict_set(zone, key, nil)
|
||||
end
|
||||
|
||||
|
||||
local function shdict_get(zone, key)
|
||||
zone = check_zone(zone)
|
||||
|
||||
if key == nil then
|
||||
return nil, "nil key"
|
||||
end
|
||||
|
||||
if type(key) ~= "string" then
|
||||
key = tostring(key)
|
||||
end
|
||||
|
||||
local key_len = #key
|
||||
if key_len == 0 then
|
||||
return nil, "empty key"
|
||||
end
|
||||
if key_len > 65535 then
|
||||
return nil, "key too long"
|
||||
end
|
||||
|
||||
local size = get_string_buf_size()
|
||||
local buf = get_string_buf(size)
|
||||
str_value_buf[0] = buf
|
||||
local value_len = get_size_ptr()
|
||||
value_len[0] = size
|
||||
|
||||
local rc = ngx_lua_ffi_shdict_get(zone, key, key_len, value_type,
|
||||
str_value_buf, value_len,
|
||||
num_value, user_flags, 0,
|
||||
is_stale, errmsg)
|
||||
if rc ~= 0 then
|
||||
if errmsg[0] then
|
||||
return nil, ffi_str(errmsg[0])
|
||||
end
|
||||
|
||||
error("failed to get the key")
|
||||
end
|
||||
|
||||
local typ = value_type[0]
|
||||
|
||||
if typ == 0 then -- LUA_TNIL
|
||||
return nil
|
||||
end
|
||||
|
||||
local flags = tonumber(user_flags[0])
|
||||
|
||||
local val
|
||||
|
||||
if typ == 4 then -- LUA_TSTRING
|
||||
if str_value_buf[0] ~= buf then
|
||||
-- ngx.say("len: ", tonumber(value_len[0]))
|
||||
buf = str_value_buf[0]
|
||||
val = ffi_str(buf, value_len[0])
|
||||
C.free(buf)
|
||||
else
|
||||
val = ffi_str(buf, value_len[0])
|
||||
end
|
||||
|
||||
elseif typ == 3 then -- LUA_TNUMBER
|
||||
val = tonumber(num_value[0])
|
||||
|
||||
elseif typ == 1 then -- LUA_TBOOLEAN
|
||||
val = (tonumber(buf[0]) ~= 0)
|
||||
|
||||
else
|
||||
error("unknown value type: " .. typ)
|
||||
end
|
||||
|
||||
if flags ~= 0 then
|
||||
return val, flags
|
||||
end
|
||||
|
||||
return val
|
||||
end
|
||||
|
||||
|
||||
local function shdict_get_stale(zone, key)
|
||||
zone = check_zone(zone)
|
||||
|
||||
if key == nil then
|
||||
return nil, "nil key"
|
||||
end
|
||||
|
||||
if type(key) ~= "string" then
|
||||
key = tostring(key)
|
||||
end
|
||||
|
||||
local key_len = #key
|
||||
if key_len == 0 then
|
||||
return nil, "empty key"
|
||||
end
|
||||
if key_len > 65535 then
|
||||
return nil, "key too long"
|
||||
end
|
||||
|
||||
local size = get_string_buf_size()
|
||||
local buf = get_string_buf(size)
|
||||
str_value_buf[0] = buf
|
||||
local value_len = get_size_ptr()
|
||||
value_len[0] = size
|
||||
|
||||
local rc = ngx_lua_ffi_shdict_get(zone, key, key_len, value_type,
|
||||
str_value_buf, value_len,
|
||||
num_value, user_flags, 1,
|
||||
is_stale, errmsg)
|
||||
if rc ~= 0 then
|
||||
if errmsg[0] then
|
||||
return nil, ffi_str(errmsg[0])
|
||||
end
|
||||
|
||||
error("failed to get the key")
|
||||
end
|
||||
|
||||
local typ = value_type[0]
|
||||
|
||||
if typ == 0 then -- LUA_TNIL
|
||||
return nil
|
||||
end
|
||||
|
||||
local flags = tonumber(user_flags[0])
|
||||
local val
|
||||
|
||||
if typ == 4 then -- LUA_TSTRING
|
||||
if str_value_buf[0] ~= buf then
|
||||
-- ngx.say("len: ", tonumber(value_len[0]))
|
||||
buf = str_value_buf[0]
|
||||
val = ffi_str(buf, value_len[0])
|
||||
C.free(buf)
|
||||
else
|
||||
val = ffi_str(buf, value_len[0])
|
||||
end
|
||||
|
||||
elseif typ == 3 then -- LUA_TNUMBER
|
||||
val = tonumber(num_value[0])
|
||||
|
||||
elseif typ == 1 then -- LUA_TBOOLEAN
|
||||
val = (tonumber(buf[0]) ~= 0)
|
||||
|
||||
else
|
||||
error("unknown value type: " .. typ)
|
||||
end
|
||||
|
||||
if flags ~= 0 then
|
||||
return val, flags, is_stale[0] == 1
|
||||
end
|
||||
|
||||
return val, nil, is_stale[0] == 1
|
||||
end
|
||||
|
||||
|
||||
local function shdict_incr(zone, key, value, init, init_ttl)
|
||||
zone = check_zone(zone)
|
||||
|
||||
if key == nil then
|
||||
return nil, "nil key"
|
||||
end
|
||||
|
||||
if type(key) ~= "string" then
|
||||
key = tostring(key)
|
||||
end
|
||||
|
||||
local key_len = #key
|
||||
if key_len == 0 then
|
||||
return nil, "empty key"
|
||||
end
|
||||
if key_len > 65535 then
|
||||
return nil, "key too long"
|
||||
end
|
||||
|
||||
if type(value) ~= "number" then
|
||||
value = tonumber(value)
|
||||
end
|
||||
num_value[0] = value
|
||||
|
||||
if init then
|
||||
local typ = type(init)
|
||||
if typ ~= "number" then
|
||||
init = tonumber(init)
|
||||
|
||||
if not init then
|
||||
error("bad init arg: number expected, got " .. typ, 2)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if init_ttl ~= nil then
|
||||
local typ = type(init_ttl)
|
||||
if typ ~= "number" then
|
||||
init_ttl = tonumber(init_ttl)
|
||||
|
||||
if not init_ttl then
|
||||
error("bad init_ttl arg: number expected, got " .. typ, 2)
|
||||
end
|
||||
end
|
||||
|
||||
if init_ttl < 0 then
|
||||
error('bad "init_ttl" argument', 2)
|
||||
end
|
||||
|
||||
if not init then
|
||||
error('must provide "init" when providing "init_ttl"', 2)
|
||||
end
|
||||
|
||||
else
|
||||
init_ttl = 0
|
||||
end
|
||||
|
||||
local rc = ngx_lua_ffi_shdict_incr(zone, key, key_len, num_value,
|
||||
errmsg, init and 1 or 0,
|
||||
init or 0, init_ttl * 1000,
|
||||
forcible)
|
||||
if rc ~= 0 then -- ~= NGX_OK
|
||||
return nil, ffi_str(errmsg[0])
|
||||
end
|
||||
|
||||
if not init then
|
||||
return tonumber(num_value[0])
|
||||
end
|
||||
|
||||
return tonumber(num_value[0]), nil, forcible[0] == 1
|
||||
end
|
||||
|
||||
|
||||
local function shdict_flush_all(zone)
|
||||
zone = check_zone(zone)
|
||||
|
||||
ngx_lua_ffi_shdict_flush_all(zone)
|
||||
end
|
||||
|
||||
|
||||
local function shdict_ttl(zone, key)
|
||||
zone = check_zone(zone)
|
||||
|
||||
if key == nil then
|
||||
return nil, "nil key"
|
||||
end
|
||||
|
||||
if type(key) ~= "string" then
|
||||
key = tostring(key)
|
||||
end
|
||||
|
||||
local key_len = #key
|
||||
if key_len == 0 then
|
||||
return nil, "empty key"
|
||||
end
|
||||
|
||||
if key_len > 65535 then
|
||||
return nil, "key too long"
|
||||
end
|
||||
|
||||
local rc = ngx_lua_ffi_shdict_get_ttl(zone, key, key_len)
|
||||
|
||||
if rc == FFI_DECLINED then
|
||||
return nil, "not found"
|
||||
end
|
||||
|
||||
return tonumber(rc) / 1000
|
||||
end
|
||||
|
||||
|
||||
local function shdict_expire(zone, key, exptime)
|
||||
zone = check_zone(zone)
|
||||
|
||||
if not exptime then
|
||||
error('bad "exptime" argument', 2)
|
||||
end
|
||||
|
||||
if key == nil then
|
||||
return nil, "nil key"
|
||||
end
|
||||
|
||||
if type(key) ~= "string" then
|
||||
key = tostring(key)
|
||||
end
|
||||
|
||||
local key_len = #key
|
||||
if key_len == 0 then
|
||||
return nil, "empty key"
|
||||
end
|
||||
|
||||
if key_len > 65535 then
|
||||
return nil, "key too long"
|
||||
end
|
||||
|
||||
local rc = ngx_lua_ffi_shdict_set_expire(zone, key, key_len,
|
||||
exptime * 1000)
|
||||
|
||||
if rc == FFI_DECLINED then
|
||||
return nil, "not found"
|
||||
end
|
||||
|
||||
-- NGINX_OK/FFI_OK
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
|
||||
local function shdict_capacity(zone)
|
||||
zone = check_zone(zone)
|
||||
|
||||
return tonumber(ngx_lua_ffi_shdict_capacity(zone))
|
||||
end
|
||||
|
||||
|
||||
local shdict_free_space
|
||||
if ngx_lua_ffi_shdict_free_space then
|
||||
shdict_free_space = function (zone)
|
||||
zone = check_zone(zone)
|
||||
|
||||
return tonumber(ngx_lua_ffi_shdict_free_space(zone))
|
||||
end
|
||||
|
||||
else
|
||||
shdict_free_space = function ()
|
||||
error("'shm:free_space()' not supported in NGINX < 1.11.7", 2)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
local _, dict = next(ngx_shared, nil)
|
||||
if dict then
|
||||
local mt = getmetatable(dict)
|
||||
if mt then
|
||||
mt = mt.__index
|
||||
if mt then
|
||||
mt.get = shdict_get
|
||||
mt.get_stale = shdict_get_stale
|
||||
mt.incr = shdict_incr
|
||||
mt.set = shdict_set
|
||||
mt.safe_set = shdict_safe_set
|
||||
mt.add = shdict_add
|
||||
mt.safe_add = shdict_safe_add
|
||||
mt.replace = shdict_replace
|
||||
mt.delete = shdict_delete
|
||||
mt.flush_all = shdict_flush_all
|
||||
mt.ttl = shdict_ttl
|
||||
mt.expire = shdict_expire
|
||||
mt.capacity = shdict_capacity
|
||||
mt.free_space = shdict_free_space
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
return _M
|
159
resty/core/time.lua
Normal file
159
resty/core/time.lua
Normal file
|
@ -0,0 +1,159 @@
|
|||
-- Copyright (C) Yichun Zhang (agentzh)
|
||||
|
||||
|
||||
local ffi = require 'ffi'
|
||||
local base = require "resty.core.base"
|
||||
|
||||
|
||||
local error = error
|
||||
local tonumber = tonumber
|
||||
local type = type
|
||||
local C = ffi.C
|
||||
local ffi_new = ffi.new
|
||||
local ffi_str = ffi.string
|
||||
local time_val = ffi_new("long[1]")
|
||||
local get_string_buf = base.get_string_buf
|
||||
local ngx = ngx
|
||||
local FFI_ERROR = base.FFI_ERROR
|
||||
local subsystem = ngx.config.subsystem
|
||||
|
||||
|
||||
local ngx_lua_ffi_now
|
||||
local ngx_lua_ffi_time
|
||||
local ngx_lua_ffi_today
|
||||
local ngx_lua_ffi_localtime
|
||||
local ngx_lua_ffi_utctime
|
||||
local ngx_lua_ffi_update_time
|
||||
|
||||
|
||||
if subsystem == 'http' then
|
||||
ffi.cdef[[
|
||||
double ngx_http_lua_ffi_now(void);
|
||||
long ngx_http_lua_ffi_time(void);
|
||||
void ngx_http_lua_ffi_today(unsigned char *buf);
|
||||
void ngx_http_lua_ffi_localtime(unsigned char *buf);
|
||||
void ngx_http_lua_ffi_utctime(unsigned char *buf);
|
||||
void ngx_http_lua_ffi_update_time(void);
|
||||
int ngx_http_lua_ffi_cookie_time(unsigned char *buf, long t);
|
||||
void ngx_http_lua_ffi_http_time(unsigned char *buf, long t);
|
||||
void ngx_http_lua_ffi_parse_http_time(const unsigned char *str, size_t len,
|
||||
long *time);
|
||||
]]
|
||||
|
||||
ngx_lua_ffi_now = C.ngx_http_lua_ffi_now
|
||||
ngx_lua_ffi_time = C.ngx_http_lua_ffi_time
|
||||
ngx_lua_ffi_today = C.ngx_http_lua_ffi_today
|
||||
ngx_lua_ffi_localtime = C.ngx_http_lua_ffi_localtime
|
||||
ngx_lua_ffi_utctime = C.ngx_http_lua_ffi_utctime
|
||||
ngx_lua_ffi_update_time = C.ngx_http_lua_ffi_update_time
|
||||
|
||||
elseif subsystem == 'stream' then
|
||||
ffi.cdef[[
|
||||
double ngx_stream_lua_ffi_now(void);
|
||||
long ngx_stream_lua_ffi_time(void);
|
||||
void ngx_stream_lua_ffi_today(unsigned char *buf);
|
||||
void ngx_stream_lua_ffi_localtime(unsigned char *buf);
|
||||
void ngx_stream_lua_ffi_utctime(unsigned char *buf);
|
||||
void ngx_stream_lua_ffi_update_time(void);
|
||||
]]
|
||||
|
||||
ngx_lua_ffi_now = C.ngx_stream_lua_ffi_now
|
||||
ngx_lua_ffi_time = C.ngx_stream_lua_ffi_time
|
||||
ngx_lua_ffi_today = C.ngx_stream_lua_ffi_today
|
||||
ngx_lua_ffi_localtime = C.ngx_stream_lua_ffi_localtime
|
||||
ngx_lua_ffi_utctime = C.ngx_stream_lua_ffi_utctime
|
||||
ngx_lua_ffi_update_time = C.ngx_stream_lua_ffi_update_time
|
||||
end
|
||||
|
||||
|
||||
function ngx.now()
|
||||
return tonumber(ngx_lua_ffi_now())
|
||||
end
|
||||
|
||||
|
||||
function ngx.time()
|
||||
return tonumber(ngx_lua_ffi_time())
|
||||
end
|
||||
|
||||
|
||||
function ngx.update_time()
|
||||
ngx_lua_ffi_update_time()
|
||||
end
|
||||
|
||||
|
||||
function ngx.today()
|
||||
-- the format of today is 2010-11-19
|
||||
local today_buf_size = 10
|
||||
local buf = get_string_buf(today_buf_size)
|
||||
ngx_lua_ffi_today(buf)
|
||||
return ffi_str(buf, today_buf_size)
|
||||
end
|
||||
|
||||
|
||||
function ngx.localtime()
|
||||
-- the format of localtime is 2010-11-19 20:56:31
|
||||
local localtime_buf_size = 19
|
||||
local buf = get_string_buf(localtime_buf_size)
|
||||
ngx_lua_ffi_localtime(buf)
|
||||
return ffi_str(buf, localtime_buf_size)
|
||||
end
|
||||
|
||||
|
||||
function ngx.utctime()
|
||||
-- the format of utctime is 2010-11-19 20:56:31
|
||||
local utctime_buf_size = 19
|
||||
local buf = get_string_buf(utctime_buf_size)
|
||||
ngx_lua_ffi_utctime(buf)
|
||||
return ffi_str(buf, utctime_buf_size)
|
||||
end
|
||||
|
||||
|
||||
if subsystem == 'http' then
|
||||
|
||||
function ngx.cookie_time(sec)
|
||||
if type(sec) ~= "number" then
|
||||
error("number argument only", 2)
|
||||
end
|
||||
|
||||
-- the format of cookie time is Mon, 28-Sep-2038 06:00:00 GMT
|
||||
-- or Mon, 28-Sep-18 06:00:00 GMT
|
||||
local cookie_time_buf_size = 29
|
||||
local buf = get_string_buf(cookie_time_buf_size)
|
||||
local used_size = C.ngx_http_lua_ffi_cookie_time(buf, sec)
|
||||
return ffi_str(buf, used_size)
|
||||
end
|
||||
|
||||
|
||||
function ngx.http_time(sec)
|
||||
if type(sec) ~= "number" then
|
||||
error("number argument only", 2)
|
||||
end
|
||||
|
||||
-- the format of http time is Mon, 28 Sep 1970 06:00:00 GMT
|
||||
local http_time_buf_size = 29
|
||||
local buf = get_string_buf(http_time_buf_size)
|
||||
C.ngx_http_lua_ffi_http_time(buf, sec)
|
||||
return ffi_str(buf, http_time_buf_size)
|
||||
end
|
||||
|
||||
|
||||
function ngx.parse_http_time(time_str)
|
||||
if type(time_str) ~= "string" then
|
||||
error("string argument only", 2)
|
||||
end
|
||||
|
||||
C.ngx_http_lua_ffi_parse_http_time(time_str, #time_str, time_val)
|
||||
|
||||
local res = time_val[0]
|
||||
if res == FFI_ERROR then
|
||||
return nil
|
||||
end
|
||||
|
||||
return tonumber(res)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
return {
|
||||
version = base.version
|
||||
}
|
94
resty/core/uri.lua
Normal file
94
resty/core/uri.lua
Normal file
|
@ -0,0 +1,94 @@
|
|||
-- Copyright (C) Yichun Zhang (agentzh)
|
||||
|
||||
|
||||
local ffi = require "ffi"
|
||||
local base = require "resty.core.base"
|
||||
|
||||
|
||||
local C = ffi.C
|
||||
local ffi_string = ffi.string
|
||||
local ngx = ngx
|
||||
local type = type
|
||||
local tostring = tostring
|
||||
local get_string_buf = base.get_string_buf
|
||||
local subsystem = ngx.config.subsystem
|
||||
|
||||
|
||||
local ngx_lua_ffi_escape_uri
|
||||
local ngx_lua_ffi_unescape_uri
|
||||
local ngx_lua_ffi_uri_escaped_length
|
||||
|
||||
|
||||
if subsystem == "http" then
|
||||
ffi.cdef[[
|
||||
size_t ngx_http_lua_ffi_uri_escaped_length(const unsigned char *src,
|
||||
size_t len);
|
||||
|
||||
void ngx_http_lua_ffi_escape_uri(const unsigned char *src, size_t len,
|
||||
unsigned char *dst);
|
||||
|
||||
size_t ngx_http_lua_ffi_unescape_uri(const unsigned char *src,
|
||||
size_t len, unsigned char *dst);
|
||||
]]
|
||||
|
||||
ngx_lua_ffi_escape_uri = C.ngx_http_lua_ffi_escape_uri
|
||||
ngx_lua_ffi_unescape_uri = C.ngx_http_lua_ffi_unescape_uri
|
||||
ngx_lua_ffi_uri_escaped_length = C.ngx_http_lua_ffi_uri_escaped_length
|
||||
|
||||
elseif subsystem == "stream" then
|
||||
ffi.cdef[[
|
||||
size_t ngx_stream_lua_ffi_uri_escaped_length(const unsigned char *src,
|
||||
size_t len);
|
||||
|
||||
void ngx_stream_lua_ffi_escape_uri(const unsigned char *src, size_t len,
|
||||
unsigned char *dst);
|
||||
|
||||
size_t ngx_stream_lua_ffi_unescape_uri(const unsigned char *src,
|
||||
size_t len, unsigned char *dst);
|
||||
]]
|
||||
|
||||
ngx_lua_ffi_escape_uri = C.ngx_stream_lua_ffi_escape_uri
|
||||
ngx_lua_ffi_unescape_uri = C.ngx_stream_lua_ffi_unescape_uri
|
||||
ngx_lua_ffi_uri_escaped_length = C.ngx_stream_lua_ffi_uri_escaped_length
|
||||
end
|
||||
|
||||
|
||||
ngx.escape_uri = function (s)
|
||||
if type(s) ~= 'string' then
|
||||
if not s then
|
||||
s = ''
|
||||
else
|
||||
s = tostring(s)
|
||||
end
|
||||
end
|
||||
local slen = #s
|
||||
local dlen = ngx_lua_ffi_uri_escaped_length(s, slen)
|
||||
-- print("dlen: ", tonumber(dlen))
|
||||
if dlen == slen then
|
||||
return s
|
||||
end
|
||||
local dst = get_string_buf(dlen)
|
||||
ngx_lua_ffi_escape_uri(s, slen, dst)
|
||||
return ffi_string(dst, dlen)
|
||||
end
|
||||
|
||||
|
||||
ngx.unescape_uri = function (s)
|
||||
if type(s) ~= 'string' then
|
||||
if not s then
|
||||
s = ''
|
||||
else
|
||||
s = tostring(s)
|
||||
end
|
||||
end
|
||||
local slen = #s
|
||||
local dlen = slen
|
||||
local dst = get_string_buf(dlen)
|
||||
dlen = ngx_lua_ffi_unescape_uri(s, slen, dst)
|
||||
return ffi_string(dst, dlen)
|
||||
end
|
||||
|
||||
|
||||
return {
|
||||
version = base.version,
|
||||
}
|
44
resty/core/utils.lua
Normal file
44
resty/core/utils.lua
Normal file
|
@ -0,0 +1,44 @@
|
|||
-- Copyright (C) Yichun Zhang (agentzh)
|
||||
|
||||
|
||||
local ffi = require "ffi"
|
||||
local base = require "resty.core.base"
|
||||
base.allows_subsystem("http")
|
||||
|
||||
|
||||
local C = ffi.C
|
||||
local ffi_str = ffi.string
|
||||
local ffi_copy = ffi.copy
|
||||
local byte = string.byte
|
||||
local str_find = string.find
|
||||
local get_string_buf = base.get_string_buf
|
||||
|
||||
|
||||
ffi.cdef[[
|
||||
void ngx_http_lua_ffi_str_replace_char(unsigned char *buf, size_t len,
|
||||
const unsigned char find, const unsigned char replace);
|
||||
]]
|
||||
|
||||
|
||||
local _M = {
|
||||
version = base.version
|
||||
}
|
||||
|
||||
|
||||
function _M.str_replace_char(str, find, replace)
|
||||
if not str_find(str, find, nil, true) then
|
||||
return str
|
||||
end
|
||||
|
||||
local len = #str
|
||||
local buf = get_string_buf(len)
|
||||
ffi_copy(buf, str)
|
||||
|
||||
C.ngx_http_lua_ffi_str_replace_char(buf, len, byte(find),
|
||||
byte(replace))
|
||||
|
||||
return ffi_str(buf, len)
|
||||
end
|
||||
|
||||
|
||||
return _M
|
160
resty/core/var.lua
Normal file
160
resty/core/var.lua
Normal file
|
@ -0,0 +1,160 @@
|
|||
-- Copyright (C) Yichun Zhang (agentzh)
|
||||
|
||||
|
||||
local ffi = require "ffi"
|
||||
local base = require "resty.core.base"
|
||||
|
||||
|
||||
local C = ffi.C
|
||||
local ffi_new = ffi.new
|
||||
local ffi_str = ffi.string
|
||||
local type = type
|
||||
local error = error
|
||||
local tostring = tostring
|
||||
local setmetatable = setmetatable
|
||||
local get_request = base.get_request
|
||||
local get_string_buf = base.get_string_buf
|
||||
local get_size_ptr = base.get_size_ptr
|
||||
local new_tab = base.new_tab
|
||||
local subsystem = ngx.config.subsystem
|
||||
|
||||
|
||||
local ngx_lua_ffi_var_get
|
||||
local ngx_lua_ffi_var_set
|
||||
|
||||
|
||||
local ERR_BUF_SIZE = 256
|
||||
|
||||
|
||||
ngx.var = new_tab(0, 0)
|
||||
|
||||
|
||||
if subsystem == "http" then
|
||||
ffi.cdef[[
|
||||
int ngx_http_lua_ffi_var_get(ngx_http_request_t *r,
|
||||
const char *name_data, size_t name_len, char *lowcase_buf,
|
||||
int capture_id, char **value, size_t *value_len, char **err);
|
||||
|
||||
int ngx_http_lua_ffi_var_set(ngx_http_request_t *r,
|
||||
const unsigned char *name_data, size_t name_len,
|
||||
unsigned char *lowcase_buf, const unsigned char *value,
|
||||
size_t value_len, unsigned char *errbuf, size_t *errlen);
|
||||
]]
|
||||
|
||||
ngx_lua_ffi_var_get = C.ngx_http_lua_ffi_var_get
|
||||
ngx_lua_ffi_var_set = C.ngx_http_lua_ffi_var_set
|
||||
|
||||
elseif subsystem == "stream" then
|
||||
ffi.cdef[[
|
||||
int ngx_stream_lua_ffi_var_get(ngx_stream_lua_request_t *r,
|
||||
const char *name_data, size_t name_len, char *lowcase_buf,
|
||||
int capture_id, char **value, size_t *value_len, char **err);
|
||||
|
||||
int ngx_stream_lua_ffi_var_set(ngx_stream_lua_request_t *r,
|
||||
const unsigned char *name_data, size_t name_len,
|
||||
unsigned char *lowcase_buf, const unsigned char *value,
|
||||
size_t value_len, unsigned char *errbuf, size_t *errlen);
|
||||
]]
|
||||
|
||||
ngx_lua_ffi_var_get = C.ngx_stream_lua_ffi_var_get
|
||||
ngx_lua_ffi_var_set = C.ngx_stream_lua_ffi_var_set
|
||||
end
|
||||
|
||||
|
||||
local value_ptr = ffi_new("unsigned char *[1]")
|
||||
local errmsg = base.get_errmsg_ptr()
|
||||
|
||||
|
||||
local function var_get(self, name)
|
||||
local r = get_request()
|
||||
if not r then
|
||||
error("no request found")
|
||||
end
|
||||
|
||||
local value_len = get_size_ptr()
|
||||
local rc
|
||||
if type(name) == "number" then
|
||||
rc = ngx_lua_ffi_var_get(r, nil, 0, nil, name, value_ptr, value_len,
|
||||
errmsg)
|
||||
|
||||
else
|
||||
if type(name) ~= "string" then
|
||||
error("bad variable name", 2)
|
||||
end
|
||||
|
||||
local name_len = #name
|
||||
local lowcase_buf = get_string_buf(name_len)
|
||||
|
||||
rc = ngx_lua_ffi_var_get(r, name, name_len, lowcase_buf, 0, value_ptr,
|
||||
value_len, errmsg)
|
||||
end
|
||||
|
||||
-- ngx.log(ngx.WARN, "rc = ", rc)
|
||||
|
||||
if rc == 0 then -- NGX_OK
|
||||
return ffi_str(value_ptr[0], value_len[0])
|
||||
end
|
||||
|
||||
if rc == -5 then -- NGX_DECLINED
|
||||
return nil
|
||||
end
|
||||
|
||||
if rc == -1 then -- NGX_ERROR
|
||||
error(ffi_str(errmsg[0]), 2)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
local function var_set(self, name, value)
|
||||
local r = get_request()
|
||||
if not r then
|
||||
error("no request found")
|
||||
end
|
||||
|
||||
if type(name) ~= "string" then
|
||||
error("bad variable name", 2)
|
||||
end
|
||||
local name_len = #name
|
||||
|
||||
local errlen = get_size_ptr()
|
||||
errlen[0] = ERR_BUF_SIZE
|
||||
local lowcase_buf = get_string_buf(name_len + ERR_BUF_SIZE)
|
||||
|
||||
local value_len
|
||||
if value == nil then
|
||||
value_len = 0
|
||||
else
|
||||
if type(value) ~= 'string' then
|
||||
value = tostring(value)
|
||||
end
|
||||
value_len = #value
|
||||
end
|
||||
|
||||
local errbuf = lowcase_buf + name_len
|
||||
local rc = ngx_lua_ffi_var_set(r, name, name_len, lowcase_buf, value,
|
||||
value_len, errbuf, errlen)
|
||||
|
||||
-- ngx.log(ngx.WARN, "rc = ", rc)
|
||||
|
||||
if rc == 0 then -- NGX_OK
|
||||
return
|
||||
end
|
||||
|
||||
if rc == -1 then -- NGX_ERROR
|
||||
error(ffi_str(errbuf, errlen[0]), 2)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
do
|
||||
local mt = new_tab(0, 2)
|
||||
mt.__index = var_get
|
||||
mt.__newindex = var_set
|
||||
|
||||
setmetatable(ngx.var, mt)
|
||||
end
|
||||
|
||||
|
||||
return {
|
||||
version = base.version
|
||||
}
|
77
resty/core/worker.lua
Normal file
77
resty/core/worker.lua
Normal file
|
@ -0,0 +1,77 @@
|
|||
-- Copyright (C) Yichun Zhang (agentzh)
|
||||
|
||||
|
||||
local ffi = require "ffi"
|
||||
local base = require "resty.core.base"
|
||||
|
||||
|
||||
local C = ffi.C
|
||||
local new_tab = base.new_tab
|
||||
local subsystem = ngx.config.subsystem
|
||||
|
||||
|
||||
local ngx_lua_ffi_worker_id
|
||||
local ngx_lua_ffi_worker_pid
|
||||
local ngx_lua_ffi_worker_count
|
||||
local ngx_lua_ffi_worker_exiting
|
||||
|
||||
|
||||
ngx.worker = new_tab(0, 4)
|
||||
|
||||
|
||||
if subsystem == "http" then
|
||||
ffi.cdef[[
|
||||
int ngx_http_lua_ffi_worker_id(void);
|
||||
int ngx_http_lua_ffi_worker_pid(void);
|
||||
int ngx_http_lua_ffi_worker_count(void);
|
||||
int ngx_http_lua_ffi_worker_exiting(void);
|
||||
]]
|
||||
|
||||
ngx_lua_ffi_worker_id = C.ngx_http_lua_ffi_worker_id
|
||||
ngx_lua_ffi_worker_pid = C.ngx_http_lua_ffi_worker_pid
|
||||
ngx_lua_ffi_worker_count = C.ngx_http_lua_ffi_worker_count
|
||||
ngx_lua_ffi_worker_exiting = C.ngx_http_lua_ffi_worker_exiting
|
||||
|
||||
elseif subsystem == "stream" then
|
||||
ffi.cdef[[
|
||||
int ngx_stream_lua_ffi_worker_id(void);
|
||||
int ngx_stream_lua_ffi_worker_pid(void);
|
||||
int ngx_stream_lua_ffi_worker_count(void);
|
||||
int ngx_stream_lua_ffi_worker_exiting(void);
|
||||
]]
|
||||
|
||||
ngx_lua_ffi_worker_id = C.ngx_stream_lua_ffi_worker_id
|
||||
ngx_lua_ffi_worker_pid = C.ngx_stream_lua_ffi_worker_pid
|
||||
ngx_lua_ffi_worker_count = C.ngx_stream_lua_ffi_worker_count
|
||||
ngx_lua_ffi_worker_exiting = C.ngx_stream_lua_ffi_worker_exiting
|
||||
end
|
||||
|
||||
|
||||
function ngx.worker.exiting()
|
||||
return ngx_lua_ffi_worker_exiting() ~= 0
|
||||
end
|
||||
|
||||
|
||||
function ngx.worker.pid()
|
||||
return ngx_lua_ffi_worker_pid()
|
||||
end
|
||||
|
||||
|
||||
function ngx.worker.id()
|
||||
local id = ngx_lua_ffi_worker_id()
|
||||
if id < 0 then
|
||||
return nil
|
||||
end
|
||||
|
||||
return id
|
||||
end
|
||||
|
||||
|
||||
function ngx.worker.count()
|
||||
return ngx_lua_ffi_worker_count()
|
||||
end
|
||||
|
||||
|
||||
return {
|
||||
_VERSION = base.version
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue