Skip to content

Commit

Permalink
feat: upgrade lua-resty-expr/radixtree to support logical expression
Browse files Browse the repository at this point in the history
Signed-off-by: spacewander <[email protected]>
  • Loading branch information
spacewander committed Mar 11, 2021
1 parent c530135 commit 7e6a254
Show file tree
Hide file tree
Showing 11 changed files with 292 additions and 62 deletions.
10 changes: 8 additions & 2 deletions apisix/plugins/fault-injection.lua
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,10 @@ local schema = {
percentage = {type = "integer", minimum = 0, maximum = 100},
vars = {
type = "array",
maxItems = 20
maxItems = 20,
item = {
type = "array",
},
}
},
required = {"http_status"},
Expand All @@ -47,7 +50,10 @@ local schema = {
percentage = {type = "integer", minimum = 0, maximum = 100},
vars = {
type = "array",
maxItems = 20
maxItems = 20,
item = {
type = "array",
},
}
},
required = {"duration"},
Expand Down
6 changes: 0 additions & 6 deletions apisix/plugins/response-rewrite.lua
Original file line number Diff line number Diff line change
Expand Up @@ -47,12 +47,6 @@ local schema = {
},
vars = {
type = "array",
items = {
description = "Nginx builtin variable name and value",
type = "array",
maxItems = 4,
minItems = 2,
},
},
},
minProperties = 1,
Expand Down
55 changes: 13 additions & 42 deletions apisix/plugins/traffic-split.lua
Original file line number Diff line number Diff line change
Expand Up @@ -33,48 +33,6 @@ local lrucache = core.lrucache.new({

local vars_schema = {
type = "array",
items = {
type = "array",
items = {
{
type = "string",
minLength = 1,
maxLength = 100
},
{
type = "string",
minLength = 1,
maxLength = 2
}
},
additionalItems = {
anyOf = {
{type = "string"},
{type = "number"},
{type = "boolean"},
{
type = "array",
items = {
anyOf = {
{
type = "string",
minLength = 1, maxLength = 100
},
{
type = "number"
},
{
type = "boolean"
}
}
},
uniqueItems = true
}
}
},
minItems = 0,
maxItems = 10
}
}


Expand Down Expand Up @@ -154,6 +112,19 @@ function _M.check_schema(conf)
return false, err
end

if conf.rules then
for _, rule in ipairs(conf.rules) do
if rule.match then
for _, m in ipairs(rule.match) do
local ok, err = expr.new(m.vars)
if not ok then
return false, "failed to validate the 'vars' expression: " .. err
end
end
end
end
end

return true
end

Expand Down
6 changes: 0 additions & 6 deletions apisix/schema_def.lua
Original file line number Diff line number Diff line change
Expand Up @@ -462,12 +462,6 @@ _M.route = {
},
vars = {
type = "array",
items = {
description = "Nginx builtin variable name and value",
type = "array",
maxItems = 4,
minItems = 2,
},
},
filter_func = {
type = "string",
Expand Down
4 changes: 2 additions & 2 deletions rockspec/apisix-master-0.rockspec
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ dependencies = {
"lua-resty-cookie = 0.1.0",
"lua-resty-session = 2.24",
"opentracing-openresty = 0.1",
"lua-resty-radixtree = 2.6.1",
"lua-resty-radixtree = 2.7.0",
"lua-protobuf = 0.3.1",
"lua-resty-openidc = 1.7.2-1",
"luafilesystem = 1.7.0-2",
Expand All @@ -59,7 +59,7 @@ dependencies = {
"binaryheap = 0.4",
"dkjson = 2.5-2",
"resty-redis-cluster = 1.02-4",
"lua-resty-expr = 1.1.0",
"lua-resty-expr = 1.2.0",
"graphql = 0.0.2",
"argparse = 0.7.1-1",
"luasocket = 3.0rc1-2",
Expand Down
4 changes: 2 additions & 2 deletions t/plugin/fault-injection.t
Original file line number Diff line number Diff line change
Expand Up @@ -802,7 +802,7 @@ done
http_status = 403,
body = "Fault Injection!\n",
vars = {
{"arg_name","==","jack"}
{"arg_name","!=","jack"}
}
},
delay = {
Expand All @@ -828,7 +828,7 @@ done
--- request
GET /t
--- response_body
invalid expression
invalid operator '!='
done
--- error_log eval
qr/failed to create vars expression:.*/
Expand Down
97 changes: 97 additions & 0 deletions t/plugin/fault-injection2.t
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
#
# 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.
#
use t::APISIX 'no_plan';

repeat_each(1);
log_level('info');
no_root_location();
no_shuffle();
master_on();

add_block_preprocessor(sub {
my ($block) = @_;

if (!$block->request) {
$block->set_value("request", "GET /t");
}

if (!$block->error_log && !$block->no_error_log) {
$block->set_value("no_error_log", "[error]");
}
});

run_tests();

__DATA__
=== TEST 1: vars rule with ! (set)
--- config
location /t {
content_by_lua_block {
local t = require("lib.test_admin").test
local code, body = t('/apisix/admin/routes/1',
ngx.HTTP_PUT,
[=[{
"plugins": {
"fault-injection": {
"abort": {
"http_status": 403,
"body": "Fault Injection!\n",
"vars": [
[
"!AND",
["arg_name","==","jack"],
["arg_age","!","<",18]
]
]
}
}
},
"upstream": {
"nodes": {
"127.0.0.1:1980": 1
},
"type": "roundrobin"
},
"uri": "/hello"
}]=]
)
if code >= 300 then
ngx.status = code
end
ngx.say(body)
}
}
--- response_body
passed
=== TEST 2: vars rule with ! (hit)
--- request
GET /hello?name=jack&age=17
--- error_code: 403
--- response_body
Fault Injection!
=== TEST 3: vars rule with ! (miss)
--- request
GET /hello?name=jack&age=18
--- response_body
hello world
2 changes: 1 addition & 1 deletion t/plugin/response-rewrite.t
Original file line number Diff line number Diff line change
Expand Up @@ -560,7 +560,7 @@ done
--- request
GET /t
--- response_body
property "vars" validation failed: failed to validate item 1: expect array to have at least 2 items
failed to validate the 'vars' expression: rule too short
--- no_error_log
[error]

Expand Down
2 changes: 1 addition & 1 deletion t/plugin/traffic-split.t
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ done
--- request
GET /t
--- response_body eval
qr/property "rules" validation failed:.* failed to validate item 2: wrong type: expected string, got number/
qr/failed to validate the 'vars' expression: invalid operator '123'/
--- no_error_log
[error]

Expand Down
105 changes: 105 additions & 0 deletions t/plugin/traffic-split2.t
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
#
# 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.
#
use t::APISIX 'no_plan';

repeat_each(1);
log_level('info');
no_root_location();
no_shuffle();
master_on();

add_block_preprocessor(sub {
my ($block) = @_;

if (!$block->request) {
$block->set_value("request", "GET /t");
}

if (!$block->error_log && !$block->no_error_log) {
$block->set_value("no_error_log", "[error]");
}
});

run_tests();

__DATA__
=== TEST 1: vars rule with ! (set)
--- config
location /t {
content_by_lua_block {
local t = require("lib.test_admin").test
local code, body = t('/apisix/admin/routes/1',
ngx.HTTP_PUT,
[=[{
"uri": "/server_port",
"plugins": {
"traffic-split": {
"rules": [
{
"match": [
{
"vars": [
["!AND",
["arg_name", "==", "jack"],
["arg_age", "!", "<", "18"]
]
]
}
],
"weighted_upstreams": [
{
"upstream": {"name": "upstream_A", "type": "roundrobin", "nodes": {"127.0.0.1:1981":1}},
"weight": 1
}
]
}
]
}
},
"upstream": {
"type": "roundrobin",
"nodes": {
"127.0.0.1:1980": 1
}
}
}]=]
)
if code >= 300 then
ngx.status = code
end
ngx.say(body)
}
}
--- response_body
passed
=== TEST 2: vars rule with ! (hit)
--- request
GET /server_port?name=jack&age=17
--- response_body chomp
1981
=== TEST 3: vars rule with ! (miss)
--- request
GET /server_port?name=jack&age=18
--- response_body chomp
1980
Loading

0 comments on commit 7e6a254

Please sign in to comment.