-
Notifications
You must be signed in to change notification settings - Fork 4.7k
/
plugins_iterator.lua
134 lines (112 loc) · 4.05 KB
/
plugins_iterator.lua
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
local responses = require "kong.tools.responses"
local singletons = require "kong.singletons"
local setmetatable = setmetatable
-- Loads a plugin config from the datastore.
-- @return plugin config table or an empty sentinel table in case of a db-miss
local function load_plugin_into_memory(api_id, consumer_id, plugin_name)
local rows, err = singletons.dao.plugins:find_all {
api_id = api_id,
consumer_id = consumer_id,
name = plugin_name
}
if err then
error(err)
end
if #rows > 0 then
for _, row in ipairs(rows) do
if api_id == row.api_id and consumer_id == row.consumer_id then
return row
end
end
end
return nil
end
--- Load the configuration for a plugin entry in the DB.
-- Given an API, a Consumer and a plugin name, retrieve the plugin's
-- configuration if it exists. Results are cached in ngx.dict
-- @param[type=string] api_id ID of the API being proxied.
-- @param[type=string] consumer_id ID of the Consumer making the request (if any).
-- @param[type=stirng] plugin_name Name of the plugin being tested for.
-- @treturn table Plugin retrieved from the cache or database.
local function load_plugin_configuration(api_id, consumer_id, plugin_name)
local plugin_cache_key = singletons.dao.plugins:cache_key(plugin_name,
api_id,
consumer_id)
local plugin, err = singletons.cache:get(plugin_cache_key, nil,
load_plugin_into_memory,
api_id, consumer_id, plugin_name)
if err then
ngx.ctx.delay_response = false
return responses.send_HTTP_INTERNAL_SERVER_ERROR(err)
end
if plugin ~= nil and plugin.enabled then
return plugin.config or {}
end
end
local function get_next(self)
local i = self.i
i = i + 1
local plugin = self.loaded_plugins[i]
if not plugin then
return nil
end
self.i = i
local ctx = self.ctx
-- load the plugin configuration in early phases
if self.access_or_cert_ctx then
local api = self.api
local plugin_configuration
local consumer = ctx.authenticated_consumer
if consumer then
local consumer_id = consumer.id
local schema = plugin.schema
if schema and not schema.no_consumer then
if api then
plugin_configuration = load_plugin_configuration(api.id, consumer_id, plugin.name)
end
if not plugin_configuration then
plugin_configuration = load_plugin_configuration(nil, consumer_id, plugin.name)
end
end
end
if not plugin_configuration then
-- Search API specific, or global
if api then
plugin_configuration = load_plugin_configuration(api.id, nil, plugin.name)
end
if not plugin_configuration then
plugin_configuration = load_plugin_configuration(nil, nil, plugin.name)
end
end
ctx.plugins_for_request[plugin.name] = plugin_configuration
end
-- return the plugin configuration
local plugins_for_request = ctx.plugins_for_request
if plugins_for_request[plugin.name] then
return plugin, plugins_for_request[plugin.name]
end
return get_next(self) -- Load next plugin
end
local plugin_iter_mt = { __call = get_next }
--- Plugins for request iterator.
-- Iterate over the plugin loaded for a request, stored in
-- `ngx.ctx.plugins_for_request`.
-- @param[type=boolean] access_or_cert_ctx Tells if the context
-- is access_by_lua_block. We don't use `ngx.get_phase()` simply because we can
-- avoid it.
-- @treturn function iterator
local function iter_plugins_for_req(loaded_plugins, access_or_cert_ctx)
local ctx = ngx.ctx
if not ctx.plugins_for_request then
ctx.plugins_for_request = {}
end
local plugin_iter_state = {
i = 0,
ctx = ctx,
api = ctx.api,
loaded_plugins = loaded_plugins,
access_or_cert_ctx = access_or_cert_ctx,
}
return setmetatable(plugin_iter_state, plugin_iter_mt)
end
return iter_plugins_for_req