Skip to content

Commit 460c3be

Browse files
bzp2010kayx23
andauthored
feat: enhance admin api filter (#12291)
Co-authored-by: Traky Deng <trakydeng@gmail.com>
1 parent 994682a commit 460c3be

File tree

8 files changed

+374
-17
lines changed

8 files changed

+374
-17
lines changed

apisix/admin/init.lua

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -250,10 +250,8 @@ local function run()
250250
else
251251
core.response.set_header("X-API-VERSION", "v2")
252252
end
253-
if resource.need_v3_filter then
254-
data = v3_adapter.filter(data)
255-
end
256253

254+
data = v3_adapter.filter(data, resource)
257255
data = strip_etcd_resp(data)
258256

259257
core.response.exit(code, data)

apisix/admin/resource.lua

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,8 @@ local type = type
2525

2626

2727
local _M = {
28-
need_v3_filter = true,
28+
list_filter_fields = {},
2929
}
30-
31-
3230
local mt = {
3331
__index = _M
3432
}

apisix/admin/routes.lua

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,5 +143,9 @@ return resource.new({
143143
name = "routes",
144144
kind = "route",
145145
schema = core.schema.route,
146-
checker = check_conf
146+
checker = check_conf,
147+
list_filter_fields = {
148+
service_id = true,
149+
upstream_id = true,
150+
},
147151
})

apisix/admin/stream_routes.lua

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,5 +73,9 @@ return resource.new({
7373
kind = "stream route",
7474
schema = core.schema.stream_route,
7575
checker = check_conf,
76-
unsupported_methods = {"patch"}
76+
unsupported_methods = { "patch" },
77+
list_filter_fields = {
78+
service_id = true,
79+
upstream_id = true,
80+
},
7781
})

apisix/admin/v3_adapter.lua

Lines changed: 44 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,16 +15,18 @@
1515
-- limitations under the License.
1616
--
1717

18+
local type = type
19+
local pairs = pairs
20+
local tonumber = tonumber
21+
local ngx = ngx
22+
local re_find = ngx.re.find
1823
local fetch_local_conf = require("apisix.core.config_local").local_conf
1924
local try_read_attr = require("apisix.core.table").try_read_attr
2025
local deepcopy = require("apisix.core.table").deepcopy
2126
local log = require("apisix.core.log")
2227
local request = require("apisix.core.request")
2328
local response = require("apisix.core.response")
2429
local table = require("apisix.core.table")
25-
local tonumber = tonumber
26-
local re_find = ngx.re.find
27-
local pairs = pairs
2830

2931
local _M = {}
3032

@@ -120,11 +122,43 @@ local function pagination(body, args)
120122
end
121123

122124

123-
local function filter(body, args)
124-
if not args.name and not args.label and not args.uri then
125-
return
125+
local function _filter(item, args, resource)
126+
if not args.filter then
127+
return true
128+
end
129+
130+
local filters, err = ngx.decode_args(args.filter or "", 100)
131+
if not filters then
132+
log.error("failed to decode filter args: ", err)
133+
return false
134+
end
135+
136+
for key, value in pairs(filters) do
137+
if not resource.list_filter_fields[key] then
138+
log.warn("filter field '", key, "' is not supported by resource: ", resource.name)
139+
goto CONTINUE
140+
end
141+
142+
if not item[key] then
143+
return false
144+
end
145+
146+
if type(value) == "table" then
147+
value = value[#value] -- get the last value in the table
148+
end
149+
150+
if item[key] ~= value then
151+
return false
152+
end
153+
154+
::CONTINUE::
126155
end
127156

157+
return true
158+
end
159+
160+
161+
local function filter(body, args, resource)
128162
for i = #body.list, 1, -1 do
129163
local name_matched = true
130164
local label_matched = true
@@ -168,14 +202,15 @@ local function filter(body, args)
168202
end
169203
end
170204

171-
if not name_matched or not label_matched or not uri_matched then
205+
if not name_matched or not label_matched or not uri_matched
206+
or not _filter(body.list[i].value, args, resource) then
172207
table.remove(body.list, i)
173208
end
174209
end
175210
end
176211

177212

178-
function _M.filter(body)
213+
function _M.filter(body, resource)
179214
if not enable_v3() then
180215
return body
181216
end
@@ -194,7 +229,7 @@ function _M.filter(body)
194229

195230
-- filter and paging logic for list query only
196231
if processed_body.list then
197-
filter(processed_body, args)
232+
filter(processed_body, args, resource)
198233

199234
-- calculate the total amount of filtered data
200235
processed_body.total = processed_body.list and #processed_body.list or 0

docs/en/latest/admin-api.md

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,42 @@ curl 'http://127.0.0.1:9180/apisix/admin/routes?name=test&uri=foo&label=' \
278278
}
279279
```
280280

281+
### Support reference filtering query
282+
283+
:::note
284+
285+
This feature was introduced in APISIX 3.13.0.
286+
287+
APISIX supports querying routes and stream routes by `service_id` and `upstream_id`. Other resources or fields are not currently supported.
288+
289+
:::
290+
291+
When getting a list of resources, it supports a `filter` for filtering resources by filters.
292+
293+
It is encoded in the following manner.
294+
295+
```text
296+
filter=escape_uri(key1=value1&key2=value2)
297+
```
298+
299+
The following example filters routes using `service_id`. Applying multiple filters simultaneously will return results that match all filter conditions.
300+
301+
```shell
302+
curl 'http://127.0.0.1:9180/apisix/admin/routes?filter=service_id%3D1' \
303+
-H "X-API-KEY: $admin_key" -X GET
304+
```
305+
306+
```json
307+
{
308+
"total": 1,
309+
"list": [
310+
{
311+
...
312+
}
313+
]
314+
}
315+
```
316+
281317
## Route
282318

283319
[Routes](./terminology/route.md) match the client's request based on defined rules, loads and executes the corresponding [plugins](#plugin), and forwards the request to the specified [Upstream](#upstream).

docs/zh/latest/admin-api.md

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,42 @@ curl 'http://127.0.0.1:9180/apisix/admin/routes?name=test&uri=foo&label=' \
284284
}
285285
```
286286

287+
### 支持引用过滤资源 {#support-reference-filtering-query}
288+
289+
:::note
290+
291+
这个特性于 APISIX 3.13.0 引入。
292+
293+
APISIX 支持通过 `service_id` 和 `upstream_id` 查询路由和 Stream 路由。现在不支持其他资源或字段。
294+
295+
:::
296+
297+
在获取资源列表时,你可以使用 `filter` 参数过滤资源。
298+
299+
它以以下方式编码:
300+
301+
```text
302+
filter=escape_uri(key1=value1&key2=value2)
303+
```
304+
305+
以下是一个使用 `service_id` 进行路由列表过滤的例子。当同时设置了多个过滤条件,结果将为它们的交集。
306+
307+
```shell
308+
curl 'http://127.0.0.1:9180/apisix/admin/routes?filter=service_id%3D1' \
309+
-H "X-API-KEY: $admin_key" -X GET
310+
```
311+
312+
```json
313+
{
314+
"total": 1,
315+
"list": [
316+
{
317+
...
318+
}
319+
]
320+
}
321+
```
322+
287323
## Route
288324

289325
Route 也称之为路由,可以通过定义一些规则来匹配客户端的请求,然后根据匹配结果加载并执行相应的插件,并把请求转发给到指定 Upstream(上游)。

0 commit comments

Comments
 (0)