条件式禁用全局插件
全局插件默认应用于所有路由,这对于强制执行组织级策略非常有用,例如日志记录、改写或流量控制。不过,有些路由可能需要从某些全局插件中豁免。
本指南将介绍如何使用路由标签和 _meta.filter 机制,为特定路由有条件地禁用全局插件。
工作原理
该方案使用三个组件:
- 路由标签:在需要跳过某些全局插件的路由上添加标签,例如
api7_disable_global_rules: response-rewrite。 serverless-pre-function:一个全局 serverless 函数,用于读取路由标签并将其注册为自定义 NGINX 变量。_meta.filter:全局插件上的条件表达式,用于评估变量,并在匹配时跳过执行。
前置条件
- API7 企业版实例正在运行。
- 已创建网关组,并且网关实例正在运行。
- 从控制台获取令牌。
方案 1:正则匹配(推荐)
该方案返 回原始路由标签字符串,并在全局插件上使用正则过滤器。它已在本地 API7 网关环境中通过全局 response-rewrite 规则完成端到端验证。
第 1 步:创建 Serverless 函数
将 serverless-pre-function 配置为全局插件,用于从路由标签注册自定义变量:
- Admin API
- ADC
curl -k "https://localhost:7443/apisix/admin/global_rules/serverless-pre-function?gateway_group_id={gateway_group_id}" -X PUT \
-H "X-API-KEY: ${API_KEY}" \
-H "Content-Type: application/json" \
-d '{
"plugins": {
"serverless-pre-function": {
"phase": "rewrite",
"functions": [
"return function(conf, ctx) local core = require \"apisix.core\" core.ctx.register_var(\"api7_disable_global_rules\", function(ctx) local route = ctx.matched_route and ctx.matched_route.value if route and route.labels then return route.labels.api7_disable_global_rules end return 1 end) end"
]
}
}
}'
adc.yaml
global_rules:
serverless-pre-function:
phase: rewrite
functions:
- |-
return function(conf, ctx)
local core = require "apisix.core"
core.ctx.register_var("api7_disable_global_rules", function(ctx)
local route = ctx.matched_route and ctx.matched_route.value
if route and route.labels then
return route.labels.api7_disable_global_rules
end
return 1
end)
end
adc sync -f adc.yaml
第 2 步:使用 _meta.filter 配置全局插件
在你希望有条件跳过的全局插件中添加 _meta.filter。以下示例会默认全局添加响应头,除非路由标签包含 response-rewrite:
- Admin API
- ADC
curl -k "https://localhost:7443/apisix/admin/global_rules/response-rewrite?gateway_group_id={gateway_group_id}" -X PUT \
-H "X-API-KEY: ${API_KEY}" \
-H "Content-Type: application/json" \
-d '{
"plugins": {
"response-rewrite": {
"headers": {
"set": {
"X-Global-Rule": "applied"
}
},
"_meta": {
"filter": [
["api7_disable_global_rules", "!", "~~", ".*response-rewrite.*"]
]
}
}
}
}'
adc.yaml
global_rules:
response-rewrite:
headers:
set:
X-Global-Rule: applied
_meta:
filter:
- - api7_disable_global_rules
- "!"
- "~~"
- ".*response-rewrite.*"
adc sync -f adc.yaml
第 3 步:为需要跳过 插件的路由添加标签
将 api7_disable_global_rules 标签添加到应绕过全局插件的路由上。
- Admin API
- ADC
# 1. 为路由创建服务
curl -k "https://localhost:7443/apisix/admin/services/global-exemption-service?gateway_group_id={gateway_group_id}" -X PUT \
-H "X-API-KEY: ${API_KEY}" \
-H "Content-Type: application/json" \
-d '{
"name": "global-exemption-service",
"upstream": {
"type": "roundrobin",
"nodes": [
{
"host": "httpbin.org",
"port": 80,
"weight": 100
}
]
}
}'
# 2. 创建带标签、可跳过全局插件的路由
curl -k "https://localhost:7443/apisix/admin/routes/global-exempt-route?gateway_group_id={gateway_group_id}" -X PUT \
-H "X-API-KEY: ${API_KEY}" \
-H "Content-Type: application/json" \
-d '{
"name": "global-exempt-route",
"paths": ["/anything/global-exempt"],
"methods": ["GET"],
"labels": {
"api7_disable_global_rules": "response-rewrite"
},
"service_id": "global-exemption-service"
}'
# 3. 创建仍应用全局插件的普通路由
curl -k "https://localhost:7443/apisix/admin/routes/global-protected-route?gateway_group_id={gateway_group_id}" -X PUT \
-H "X-API-KEY: ${API_KEY}" \
-H "Content-Type: application/json" \
-d '{
"name": "global-protected-route",
"paths": ["/anything/global-protected"],
"methods": ["GET"],
"service_id": "global-exemption-service"
}'
adc.yaml
services:
- name: global-exemption-service
upstream:
nodes:
- host: httpbin.org
port: 80
weight: 1
routes:
- name: global-exempt-route
uris:
- /anything/global-exempt
labels:
api7_disable_global_rules: response-rewrite
- name: global-protected-route
uris:
- /anything/global-protected
adc sync -f adc.yaml
验证
向带标签的路由发送请求:
curl -i "http://127.0.0.1:9080/anything/global-exempt"
由于 response-rewrite 被跳过,响应中不应包含 X-Global-Rule 响应头。
向未带标签的路由发送请求:
curl -i "http://127.0.0.1:9080/anything/global-protected"
由于全局插件处于激活状态,响应中应包含 X-Global-Rule: applied。