This is an automated email from the ASF dual-hosted git repository.
shreemaan-abhishek pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/apisix.git
The following commit(s) were added to refs/heads/master by this push:
new d3f198486 fix(attach-consumer-label): always drop client-supplied
configured headers (#13590)
d3f198486 is described below
commit d3f198486af31518e1bf039fc604d90008f732f5
Author: Shreemaan Abhishek <[email protected]>
AuthorDate: Wed Jun 24 17:16:58 2026 +0800
fix(attach-consumer-label): always drop client-supplied configured headers
(#13590)
---
apisix/plugins/attach-consumer-label.lua | 15 +++--
docs/en/latest/plugins/attach-consumer-label.md | 2 +-
docs/zh/latest/plugins/attach-consumer-label.md | 2 +-
t/plugin/attach-consumer-label.t | 90 +++++++++++++++++++++++++
4 files changed, 100 insertions(+), 9 deletions(-)
diff --git a/apisix/plugins/attach-consumer-label.lua
b/apisix/plugins/attach-consumer-label.lua
index 6d3396a02..d76cbf99b 100644
--- a/apisix/plugins/attach-consumer-label.lua
+++ b/apisix/plugins/attach-consumer-label.lua
@@ -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
diff --git a/docs/en/latest/plugins/attach-consumer-label.md
b/docs/en/latest/plugins/attach-consumer-label.md
index 2f5557d8e..9bfecda01 100644
--- a/docs/en/latest/plugins/attach-consumer-label.md
+++ b/docs/en/latest/plugins/attach-consumer-label.md
@@ -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 val [...]
## Examples
diff --git a/docs/zh/latest/plugins/attach-consumer-label.md
b/docs/zh/latest/plugins/attach-consumer-label.md
index 5981cc737..10fc6d0c1 100644
--- a/docs/zh/latest/plugins/attach-consumer-label.md
+++ b/docs/zh/latest/plugins/attach-consumer-label.md
@@ -40,7 +40,7 @@ description: attach-consumer-label 插件将自定义消费者标签附加到经
| 名称 | 类型 | 必选项 | 默认值 | 有效值 | 描述
|
|----------|--------|--------|--------|--------|----------------------------------------------------------------------------------------------------------------------------------------------------|
-| headers | object | 是 | | |
要附加到请求标头的消费者标签键值对,其中键是请求标头名称(例如 `X-Consumer-Role`),值是对消费者标签键的引用(例如
`$role`)。注意,值必须以美元符号(`$`)开头。如果消费者上未配置被引用的标签,则对应的请求标头将不会被附加。 |
+| headers | object | 是 | | |
要附加到请求标头的消费者标签键值对,其中键是请求标头名称(例如 `X-Consumer-Role`),值是对消费者标签键的引用(例如
`$role`)。注意,值必须以美元符号(`$`)开头。客户端传入的同名请求标头会被先行移除,因此上游只会看到网关设置的值。如果消费者上未配置被引用的标签,则对应的请求标头将不会被附加。
|
## 示例
diff --git a/t/plugin/attach-consumer-label.t b/t/plugin/attach-consumer-label.t
index 615b1cf09..db0ef634a 100644
--- a/t/plugin/attach-consumer-label.t
+++ b/t/plugin/attach-consumer-label.t
@@ -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]