feat(proxy-rewrite): support multiple same-name headers in headers.add/set#13597
feat(proxy-rewrite): support multiple same-name headers in headers.add/set#13597AlinsRan wants to merge 4 commits into
Conversation
Allow headers.set and headers.add values to be an array (e.g. "foo": ["v1", "v2"]), producing multiple headers with the same name: - set replaces any incoming header with the listed values; - add appends the listed values to the existing ones. The map-based headers schema previously could not express same-name multi-value headers (a JSON object can't hold two values for one key); the array form closes that gap. remove is unchanged (it already takes an array of names). Backward compatible: string/number values keep working. Closes apache#13163
The echo helper joined same-name headers with ", ", so the assertions
("x-multi: val1, val2") could not tell a genuine multi-header result apart
from a single comma-joined value. Emit one line per header occurrence and
assert the repeated "x-multi: ..." lines, so the test actually proves that
set/add with an array produces multiple headers with the same name.
…y comment - t/plugin/proxy-rewrite.t: add cases where each array element of headers.set/add mixes $1 (regex_uri capture) and $http_x_src (nginx variable), since the docs promise per-element variable/capture support. - proxy-rewrite.lua: clarify the add_header guard comment — it filters nil (which throws); an empty string is a valid value and is intentionally kept.
shreemaan-abhishek
left a comment
There was a problem hiding this comment.
I think both "multiple values for same header" and "same header with multiple values - (comma separated or not)" are the same.
So even without this PR, set can already set multiple values for a header by specifying comma separated values.
The add feature in this PR is nice to have.
I don't think they're fully interchangeable. A headers.set object can't express same-name multi-value headers at all (a JSON object can't hold two values for one key), and emitting repeated lines is a first-class, intentional behavior — both HTTP and the underlying OpenResty support it (ngx.req.set_header(name, {...})). The array closes that gap. Real headers that rely on multiple same-name fields rather than a comma list:
|
Description
Allow
headers.setandheaders.addvalues inproxy-rewriteto be an array, producing multiple headers with the same name:setwith an array replaces any incoming header with the listed values.addwith an array appends the listed values to the existing ones.removeis unchanged (it already takes an array of names).Why
proxy-rewritemodelsheaders.add/setas a JSON object (map), which structurally cannot express same-name multi-value headers — a JSON object can't hold two values for one key. This is a real gap vs. other gateways that model header transforms as an ordered list of (name, value) pairs (Kongrequest-transformerappend.headers, Envoyrequest_headers_to_add, HAProxyadd-header). The array form closes it. Genuine use cases: gRPC metadata (repeated keys → repeated HTTP/2 headers) and backends/auth proxies that read repeated custom headers.Fully backward compatible: existing string/number values keep working; the array is an additive schema option. Each element still supports NGINX variables and
regex_uricaptures.This also gives the clean answer to the
remove + addordering confusion in #11587 — multi-value is a data-model feature, not an operation-order one.Which issue(s) this PR fixes
Closes #11587
Closes #13163
Changes
apisix/plugins/proxy-rewrite.lua: schema allowsarray<string|number>foradd/setvalues; apply loop resolves each element (set→ oneset_headerwith a table;add→ oneadd_headerper element).t/plugin/proxy-rewrite.t: tests forset(replace with multiple) andadd(append multiple);t/lib/server.lua: echo helper joining same-name headers.docs/{en,zh}/.../proxy-rewrite.md: attribute docs + example.Checklist