File: ctx.lua

package info (click to toggle)
lua-resty-core 0.1.32-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 2,268 kB
  • sloc: sh: 207; perl: 143; makefile: 26
file content (147 lines) | stat: -rw-r--r-- 3,796 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
-- 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 setmetatable = setmetatable
local type = type
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 *in_ssl_phase,
        int *ssl_ctx_ref);
    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 *in_ssl_phase, int *ssl_ctx_ref);
    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
}


-- use a new ctxs table to make LuaJIT JIT compiler happy to generate more
-- efficient machine code.
local ctxs = {}
registry.ngx_lua_ctx_tables = ctxs


local get_ctx_table
do
    local in_ssl_phase = ffi.new("int[1]")
    local ssl_ctx_ref = ffi.new("int[1]")

    function get_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, in_ssl_phase, ssl_ctx_ref)
        if ctx_ref == FFI_NO_REQ_CTX then
            error("no request ctx found")
        end

        if ctx_ref < 0 then
            ctx_ref = ssl_ctx_ref[0]
            if ctx_ref > 0 and ctxs[ctx_ref] then
                if in_ssl_phase[0] ~= 0 then
                    return ctxs[ctx_ref]
                end

                if not ctx then
                    ctx = new_tab(0, 4)
                end

                ctx = setmetatable(ctx, ctxs[ctx_ref])

            else
                if in_ssl_phase[0] ~= 0 then
                    if not ctx then
                        ctx = new_tab(1, 4)
                    end

                    -- to avoid creating another table, we assume the users
                    -- won't overwrite the `__index` key
                    ctx.__index = ctx

                elseif not ctx then
                    ctx = new_tab(0, 4)
                end
            end

            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
end
register_getter("ctx", get_ctx_table)
_M.get_ctx_table = get_ctx_table


local function set_ctx_table(ctx)
    local ctx_type = type(ctx)
    if ctx_type ~= "table" then
        error("ctx should be a table while getting a " .. ctx_type)
    end

    local r = get_request()

    if not r then
        error("no request found")
    end

    local ctx_ref = ngx_lua_ffi_get_ctx_ref(r, nil, nil)
    if ctx_ref == FFI_NO_REQ_CTX then
        error("no request ctx found")
    end

    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