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 79a87e559f feat(core): make the readable request header count
configurable (#14136)
79a87e559f is described below
commit 79a87e559f6bec9a018ca4466e31b43ef9650e81
Author: Shreemaan Abhishek <[email protected]>
AuthorDate: Wed Nov 4 14:26:10 2026 +0800
feat(core): make the readable request header count configurable (#14136)
---
apisix/cli/config.lua | 1 +
apisix/cli/schema.lua | 7 ++++++
apisix/core/request.lua | 27 +++++++++++++++++---
conf/config.yaml.example | 3 +++
t/core/request.t | 65 ++++++++++++++++++++++++++++++++++++++++++++++++
5 files changed, 100 insertions(+), 3 deletions(-)
diff --git a/apisix/cli/config.lua b/apisix/cli/config.lua
index 2ce29a0a47..07da7cb2e5 100644
--- a/apisix/cli/config.lua
+++ b/apisix/cli/config.lua
@@ -49,6 +49,7 @@ local _M = {
normalize_uri_like_servlet = false,
match_uri_encoded_slash = false,
max_post_args_readable_size = 64,
+ max_request_headers_readable = 100,
router = {
http = "radixtree_host_uri",
ssl = "radixtree_sni"
diff --git a/apisix/cli/schema.lua b/apisix/cli/schema.lua
index e52453e56c..84c2fba248 100644
--- a/apisix/cli/schema.lua
+++ b/apisix/cli/schema.lua
@@ -288,6 +288,13 @@ local config_schema = {
description = "cap (in MB) on the request body read for
post_arg.* "
.. "route matching; 0 disables the limit",
},
+ max_request_headers_readable = {
+ type = "integer",
+ minimum = 0,
+ default = 100,
+ description = "max number of request headers plugins can
read; "
+ .. "0 disables the limit",
+ },
}
},
nginx_config = {
diff --git a/apisix/core/request.lua b/apisix/core/request.lua
index 97c74cc723..950ef1a8df 100644
--- a/apisix/core/request.lua
+++ b/apisix/core/request.lua
@@ -25,6 +25,8 @@ local json = require("apisix.core.json")
local io = require("apisix.core.io")
local multipart = require("multipart")
local core_str = require("apisix.core.string")
+local config_local = require("apisix.core.config_local")
+local try_read_attr = require("apisix.core.table").try_read_attr
local req_add_header
if ngx.config.subsystem == "http" then
local ngx_req = require "ngx.req"
@@ -51,28 +53,47 @@ local req_set_header = ngx.req.set_header
local CONTENT_TYPE_JSON = "application/json"
local CONTENT_TYPE_FORM_URLENCODED = "application/x-www-form-urlencoded"
local CONTENT_TYPE_MULTIPART_FORM = "multipart/form-data"
+local DEFAULT_MAX_HEADERS = 100
local _M = {}
+local max_headers
+local function get_max_headers()
+ if max_headers then
+ return max_headers
+ end
+
+ local local_conf, err = config_local.local_conf()
+ if not local_conf then
+ log.error("failed to get local conf: ", err)
+ return DEFAULT_MAX_HEADERS
+ end
+
+ max_headers = try_read_attr(local_conf, "apisix",
"max_request_headers_readable")
+ or DEFAULT_MAX_HEADERS
+ return max_headers
+end
+
+
local function _headers(ctx)
if not ctx then
ctx = ngx.ctx.api_ctx
end
if not is_apisix_or then
- return get_headers()
+ return get_headers(get_max_headers())
end
if a6_request.is_request_header_set() then
a6_request.clear_request_header()
- ctx.headers = get_headers()
+ ctx.headers = get_headers(get_max_headers())
end
local headers = ctx.headers
if not headers then
- headers = get_headers()
+ headers = get_headers(get_max_headers())
ctx.headers = headers
end
diff --git a/conf/config.yaml.example b/conf/config.yaml.example
index c654eb4ca9..25a4780a62 100644
--- a/conf/config.yaml.example
+++ b/conf/config.yaml.example
@@ -77,6 +77,9 @@ apisix:
# original request line, so the upstream
receives %2F unchanged.
max_post_args_readable_size: 64 # Cap (in MB) on the request body read
when matching `post_arg.*`
# route predicates for JSON and
multipart requests. Set to 0 to disable the limit.
+ max_request_headers_readable: 100 # Max number of request headers plugins
can read. Headers past this
+ # count are invisible to plugins but
still forwarded to the upstream.
+ # Set to 0 to disable the limit.
router:
http: radixtree_host_uri # radixtree_host_uri: match route by host and
URI
diff --git a/t/core/request.t b/t/core/request.t
index a99311aa54..caba0be349 100644
--- a/t/core/request.t
+++ b/t/core/request.t
@@ -611,3 +611,68 @@ header: new
body: nil
err: request size 17 is greater than the maximum size 8 allowed
kind: too_large
+
+
+
+=== TEST 20: plugins read the first 100 request headers by default
+--- config
+ location /t {
+ content_by_lua_block {
+ local core = require("apisix.core")
+ ngx.ctx.api_ctx = {}
+ local ctx = ngx.ctx.api_ctx
+ local count = 0
+ for _ in pairs(core.request.headers(ctx)) do
+ count = count + 1
+ end
+ ngx.say("count: ", count)
+ ngx.say("x-last: ", core.request.header(ctx, "X-Last"))
+ }
+ }
+--- more_headers eval
+CORE::join("", map { "X-Pad-$_: $_\n" } 1 .. 100) . "X-Last: yes\n"
+--- response_body
+count: 100
+x-last: nil
+
+
+
+=== TEST 21: max_request_headers_readable raises the limit
+--- yaml_config
+apisix:
+ node_listen: 1984
+ max_request_headers_readable: 200
+--- config
+ location /t {
+ content_by_lua_block {
+ local core = require("apisix.core")
+ ngx.ctx.api_ctx = {}
+ local ctx = ngx.ctx.api_ctx
+ ngx.say("x-last: ", core.request.header(ctx, "X-Last"))
+ }
+ }
+--- more_headers eval
+CORE::join("", map { "X-Pad-$_: $_\n" } 1 .. 100) . "X-Last: yes\n"
+--- response_body
+x-last: yes
+
+
+
+=== TEST 22: max_request_headers_readable 0 reads all headers
+--- yaml_config
+apisix:
+ node_listen: 1984
+ max_request_headers_readable: 0
+--- config
+ location /t {
+ content_by_lua_block {
+ local core = require("apisix.core")
+ ngx.ctx.api_ctx = {}
+ local ctx = ngx.ctx.api_ctx
+ ngx.say("x-last: ", core.request.header(ctx, "X-Last"))
+ }
+ }
+--- more_headers eval
+CORE::join("", map { "X-Pad-$_: $_\n" } 1 .. 300) . "X-Last: yes\n"
+--- response_body
+x-last: yes