-
Notifications
You must be signed in to change notification settings - Fork 2.4k
/
wasm.lua
194 lines (159 loc) · 5.29 KB
/
wasm.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
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
--
-- Licensed to the Apache Software Foundation (ASF) under one or more
-- contributor license agreements. See the NOTICE file distributed with
-- this work for additional information regarding copyright ownership.
-- The ASF licenses this file to You under the Apache License, Version 2.0
-- (the "License"); you may not use this file except in compliance with
-- the License. You may obtain a copy of the License at
--
-- http://www.apache.org/licenses/LICENSE-2.0
--
-- Unless required by applicable law or agreed to in writing, software
-- distributed under the License is distributed on an "AS IS" BASIS,
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-- See the License for the specific language governing permissions and
-- limitations under the License.
--
local core = require("apisix.core")
local support_wasm, wasm = pcall(require, "resty.proxy-wasm")
local ngx_var = ngx.var
local schema = {
type = "object",
properties = {
conf = {
type = "string",
minLength = 1,
},
},
required = {"conf"}
}
local _M = {}
local function check_schema(conf)
return core.schema.check(schema, conf)
end
local function get_plugin_ctx_key(ctx)
return ctx.conf_type .. "#" .. ctx.conf_id
end
local function fetch_plugin_ctx(conf, ctx, plugin)
if not conf.plugin_ctxs then
conf.plugin_ctxs = {}
end
local ctxs = conf.plugin_ctxs
local key = get_plugin_ctx_key(ctx)
local plugin_ctx = ctxs[key]
local err
if not plugin_ctx then
plugin_ctx, err = wasm.on_configure(plugin, conf.conf)
if not plugin_ctx then
return nil, err
end
ctxs[key] = plugin_ctx
end
return plugin_ctx
end
local function http_request_wrapper(self, conf, ctx)
local name = self.name
local plugin_ctx, err = fetch_plugin_ctx(conf, ctx, self.plugin)
if not plugin_ctx then
core.log.error(name, ": failed to fetch wasm plugin ctx: ", err)
return 503
end
local ok, err = wasm.on_http_request_headers(plugin_ctx)
if not ok then
core.log.error(name, ": failed to run wasm plugin: ", err)
return 503
end
-- $wasm_process_req_body is predefined in ngx_tpl.lua
local handle_body = ngx_var.wasm_process_req_body
if handle_body ~= '' then
-- reset the flag so we can use it for the next Wasm plugin
-- use ngx.var to bypass the cache
ngx_var.wasm_process_req_body = ''
local body, err = core.request.get_body()
if err ~= nil then
core.log.error(name, ": failed to get request body: ", err)
return 503
end
local ok, err = wasm.on_http_request_body(plugin_ctx, body, true)
if not ok then
core.log.error(name, ": failed to run wasm plugin: ", err)
return 503
end
end
end
local function header_filter_wrapper(self, conf, ctx)
local name = self.name
local plugin_ctx, err = fetch_plugin_ctx(conf, ctx, self.plugin)
if not plugin_ctx then
core.log.error(name, ": failed to fetch wasm plugin ctx: ", err)
return 503
end
local ok, err = wasm.on_http_response_headers(plugin_ctx)
if not ok then
core.log.error(name, ": failed to run wasm plugin: ", err)
return 503
end
-- $wasm_process_resp_body is predefined in ngx_tpl.lua
local handle_body = ngx_var.wasm_process_resp_body
if handle_body ~= '' then
-- reset the flag so we can use it for the next Wasm plugin
-- use ngx.var to bypass the cache
ngx_var.wasm_process_resp_body = ""
ctx["wasm_" .. name .. "_process_resp_body"] = true
end
end
local function body_filter_wrapper(self, conf, ctx)
local name = self.name
local enabled = ctx["wasm_" .. name .. "_process_resp_body"]
if not enabled then
return
end
local plugin_ctx, err = fetch_plugin_ctx(conf, ctx, self.plugin)
if not plugin_ctx then
core.log.error(name, ": failed to fetch wasm plugin ctx: ", err)
return
end
local ok, err = wasm.on_http_response_body(plugin_ctx)
if not ok then
core.log.error(name, ": failed to run wasm plugin: ", err)
return
end
end
function _M.require(attrs)
if not support_wasm then
return nil, "need to build APISIX-Base to support wasm"
end
local name = attrs.name
local priority = attrs.priority
local plugin, err = wasm.load(name, attrs.file)
if not plugin then
return nil, err
end
local mod = {
version = 0.1,
name = name,
priority = priority,
schema = schema,
check_schema = check_schema,
plugin = plugin,
type = "wasm",
}
if attrs.http_request_phase == "rewrite" then
mod.rewrite = function (conf, ctx)
return http_request_wrapper(mod, conf, ctx)
end
else
mod.access = function (conf, ctx)
return http_request_wrapper(mod, conf, ctx)
end
end
mod.header_filter = function (conf, ctx)
return header_filter_wrapper(mod, conf, ctx)
end
mod.body_filter = function (conf, ctx)
return body_filter_wrapper(mod, conf, ctx)
end
-- the returned values need to be the same as the Lua's 'require'
return true, mod
end
return _M