Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 8 additions & 7 deletions apisix/plugins/attach-consumer-label.lua
Original file line number Diff line number Diff line change
Expand Up @@ -46,20 +46,21 @@ function _M.check_schema(conf)
end

function _M.before_proxy(conf, ctx)
-- check if the consumer is exists in the context
if not ctx.consumer then
local labels = ctx.consumer and ctx.consumer.labels

-- no labels to map: just drop client-supplied copies of the configured headers
if not labels then
for header in pairs(conf.headers) do
core.request.set_header(ctx, header, nil)
end
return
end

local labels = ctx.consumer.labels
core.log.info("consumer username: ", ctx.consumer.username, " labels: ",
core.json.delay_encode(labels))
if not labels then
return
end

for header, label_key in pairs(conf.headers) do
-- remove leading $ character
-- remove leading $ character, set value (nil clears any client-supplied copy)
local label_value = labels[label_key:sub(2)]
core.request.set_header(ctx, header, label_value)
end
Expand Down
2 changes: 1 addition & 1 deletion docs/en/latest/plugins/attach-consumer-label.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ The `attach-consumer-label` Plugin attaches custom consumer-related labels, in a

| Name | Type | Required | Default | Valid values | Description |
|----------|--------|----------|---------|--------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| headers | object | True | | | Key-value pairs of Consumer labels to be attached to request headers, where key is the request header name, such as `X-Consumer-Role`, and the value is a reference to the custom label key, such as `$role`. Note that the value should always start with a dollar sign (`$`). If a referenced Consumer label value is not configured on the Consumer, the corresponding header will not be attached to the request. |
| headers | object | True | | | Key-value pairs of Consumer labels to be attached to request headers, where key is the request header name, such as `X-Consumer-Role`, and the value is a reference to the custom label key, such as `$role`. Note that the value should always start with a dollar sign (`$`). Any client-supplied value of a configured header is always removed first, so the Upstream only ever sees the gateway-set value. If a referenced Consumer label value is not configured on the Consumer, the corresponding header will not be attached to the request. |

## Examples

Expand Down
2 changes: 1 addition & 1 deletion docs/zh/latest/plugins/attach-consumer-label.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ description: attach-consumer-label 插件将自定义消费者标签附加到经

| 名称 | 类型 | 必选项 | 默认值 | 有效值 | 描述 |
|----------|--------|--------|--------|--------|----------------------------------------------------------------------------------------------------------------------------------------------------|
| headers | object | 是 | | | 要附加到请求标头的消费者标签键值对,其中键是请求标头名称(例如 `X-Consumer-Role`),值是对消费者标签键的引用(例如 `$role`)。注意,值必须以美元符号(`$`)开头。如果消费者上未配置被引用的标签,则对应的请求标头将不会被附加。 |
| headers | object | 是 | | | 要附加到请求标头的消费者标签键值对,其中键是请求标头名称(例如 `X-Consumer-Role`),值是对消费者标签键的引用(例如 `$role`)。注意,值必须以美元符号(`$`)开头。客户端传入的同名请求标头会被先行移除,因此上游只会看到网关设置的值。如果消费者上未配置被引用的标签,则对应的请求标头将不会被附加。 |

## 示例

Expand Down
90 changes: 90 additions & 0 deletions t/plugin/attach-consumer-label.t
Original file line number Diff line number Diff line change
Expand Up @@ -463,3 +463,93 @@ X-Global-Consumer-Company: api7
X-Global-Consumer-Department: devops
--- no_error_log
[error]



=== TEST 16: add a no-label consumer and a route that echoes upstream-received headers
--- config
location /t {
content_by_lua_block {
local t = require("lib.test_admin").test
local code, body = t('/apisix/admin/consumers',
ngx.HTTP_PUT,
[[{
"username": "bob"
}]]
)

if code >= 300 then
ngx.status = code
ngx.say(body)
return
end

local code, body = t('/apisix/admin/consumers/bob/credentials/a',
ngx.HTTP_PUT,
[[{
"plugins": {
"key-auth": {
"key": "key-bob"
}
}
}]]
)

if code >= 300 then
ngx.status = code
ngx.say(body)
return
end

local code, body = t('/apisix/admin/routes/2',
ngx.HTTP_PUT,
[[{
"uri": "/print_request_received",
"plugins": {
"key-auth": {},
"attach-consumer-label": {
"headers": {
"X-Consumer-Role": "$role"
}
}
},
"upstream": {
"nodes": {
"127.0.0.1:1980": 1
},
"type": "roundrobin"
}
}]]
)

if code >= 300 then
ngx.status = code
ngx.say(body)
return
end

ngx.say(body)
}
}
--- request
GET /t
--- response_body
passed
--- no_error_log
[error]



=== TEST 17: client-supplied configured header is dropped at the upstream when the consumer has no labels
# the upstream body must contain the authenticated consumer marker
# (x-consumer-username: bob) AND must not contain the client-supplied
# x-consumer-role, proving it was stripped before proxying upstream
--- request
GET /print_request_received
--- more_headers
apikey: key-bob
X-Consumer-Role: admin
--- response_body_like eval
qr/(?s)^(?!.*x-consumer-role).*x-consumer-username: bob/
--- no_error_log
[error]
Loading