Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(request-transformer): unpredictable overriding result from rename header to existing header caused by pairs disorder #9442

Merged
merged 5 commits into from
Oct 21, 2022

Conversation

windmgc
Copy link
Member

@windmgc windmgc commented Sep 17, 2022

Summary

This PR fixes a bug in the request-transformer plugin, where the rename header cannot override an already existing header steadily.

If a header A-header already exists with a value A-value in the request, and the request-transformer plugin is configured to rename B-header(with a value B-value) to A-header(with different format, like all chars are capitalized), then the upstream request will contain an A-header with possibly A-value or B-value. This unpredictable behaviour may caused by pairs function disorder behaviour(Again!).

The code flow is as follows:

A header table is fetched by ngx.req.get_headers and used later for storing upstream request headers

local headers = get_headers()

Then the rename header list will be iterated

-- Rename headers(s)
for _, old_name, new_name in iter(conf.rename.headers) do
old_name = old_name:lower()
if headers[old_name] then
local value = headers[old_name]
headers[new_name] = value
headers[old_name] = nil
headers_to_remove[old_name] = true
end
end

Note that in this code block, the new_name will be directly used for setting value in the table, and the headers fetched by ngx.req.get_headers() are in lower case, so if new_name is an upper-case, then two keys with different format will exist in the header table.

And that will lead to the unpredictable iterating sequence in setting headers:

for k, v in pairs(headers) do
if string_lower(k) == "host" then
ngx_var.upstream_host = v
end
ngx.req.set_header(k, normalize_multi_header(v))

Full changelog

  • Fix unpredictable overriding result from rename header to existing header in request-transformer plugin, by normalizing the header name(set to lower case)
  • Cleanup duplicate tests and add related test

Issue reference

Fix FTI-4319 and #9418

@windmgc windmgc modified the milestones: 3.0.1, 3.1 Sep 27, 2022
@hanshuebner
Copy link
Contributor

hanshuebner commented Oct 12, 2022

To prevent such issues from happening, would it not make sense to have all headers tables have this metatable:

{
  __newindex=function (t,k,v) rawset(t,k:lower(),v) end,
  __index=function(t,k) return t[k:lower()] end,
}

That way, the normalization to lower case would happen automatically.

@windmgc
Copy link
Member Author

windmgc commented Oct 13, 2022

To prevent such issues from happening, would it not make sense to have all headers tables have this metatable:

{
  __newindex=function (t,k,v) rawset(t,k:lower(),v) end,
  __index=function(t,k) return t[k:lower()] end,
}

That way, the normalization to lower case would happen automatically.

It's a good idea but needs changes in the PDK(more like a patch on the original OpenResty's ngx.req.get_headers, I think they already have __index to do the lowercase work but I don't know why they did not have the __newindex behaviour, maybe because of the ambiguity about underscore)

I feel it is better to open another PR for this change, and doing another lower case here is not very harmful, WDYT?

@chronolaw
Copy link
Contributor

Need a change log entry.

CHANGELOG.md Outdated Show resolved Hide resolved
@windmgc windmgc force-pushed the fix-request-transformer-rename-override branch 2 times, most recently from 238e138 to 1fda03c Compare October 18, 2022 06:18
CHANGELOG.md Outdated Show resolved Hide resolved
@windmgc windmgc force-pushed the fix-request-transformer-rename-override branch 3 times, most recently from 1fbb32f to 36d23ea Compare October 20, 2022 02:28
@windmgc windmgc force-pushed the fix-request-transformer-rename-override branch from 36d23ea to c48e5e1 Compare October 21, 2022 06:39
@windmgc windmgc force-pushed the fix-request-transformer-rename-override branch from c48e5e1 to f88f2c6 Compare October 21, 2022 06:48
@fffonion fffonion merged commit 2ce112f into Kong:master Oct 21, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants