diff --git a/kong/runloop/balancer/init.lua b/kong/runloop/balancer/init.lua index e3a3eae264b4..e7cd0f66ec64 100644 --- a/kong/runloop/balancer/init.lua +++ b/kong/runloop/balancer/init.lua @@ -131,10 +131,9 @@ local function get_value_to_hash(upstream, ctx) identifier = var.remote_addr elseif hash_on == "header" then - identifier = ngx.req.get_headers()[upstream[header_field_name]] - if type(identifier) == "table" then - identifier = table_concat(identifier) - end + -- since nginx 1.23.0/openresty 1.25.3.1 + -- ngx.var will automatically combine all header values with identical name + identifier = var["http_" .. upstream[header_field_name]] elseif hash_on == "cookie" then identifier = var["cookie_" .. upstream.hash_on_cookie] diff --git a/spec/02-integration/05-proxy/10-balancer/03-consistent-hashing_spec.lua b/spec/02-integration/05-proxy/10-balancer/03-consistent-hashing_spec.lua index 97b2c9a724ba..ab6bde942e6f 100644 --- a/spec/02-integration/05-proxy/10-balancer/03-consistent-hashing_spec.lua +++ b/spec/02-integration/05-proxy/10-balancer/03-consistent-hashing_spec.lua @@ -58,6 +58,45 @@ for _, strategy in helpers.each_strategy() do ["hashme"] = "just a value", }) assert.are.equal(requests, oks) + assert.logfile().has.line("trying to get peer with value to hash: \\[just a value\\]") + + -- collect server results; hitcount + -- one should get all the hits, the other 0 + local count1 = server1:shutdown() + local count2 = server2:shutdown() + + -- verify + assert(count1.total == 0 or count1.total == requests, "counts should either get 0 or ALL hits") + assert(count2.total == 0 or count2.total == requests, "counts should either get 0 or ALL hits") + assert(count1.total + count2.total == requests) + end) + + it("hashing on multiple headers", function() + local requests = bu.SLOTS * 2 -- go round the balancer twice + + bu.begin_testcase_setup(strategy, bp) + local upstream_name, upstream_id = bu.add_upstream(bp, { + hash_on = "header", + hash_on_header = "hashme", + }) + local port1 = bu.add_target(bp, upstream_id, localhost) + local port2 = bu.add_target(bp, upstream_id, localhost) + local api_host = bu.add_api(bp, upstream_name) + bu.end_testcase_setup(strategy, bp) + + -- setup target servers + local server1 = https_server.new(port1, localhost) + local server2 = https_server.new(port2, localhost) + server1:start() + server2:start() + + -- Go hit them with our test requests + local oks = bu.client_requests(requests, { + ["Host"] = api_host, + ["hashme"] = { "1st value", "2nd value", }, + }) + assert.are.equal(requests, oks) + assert.logfile().has.line("trying to get peer with value to hash: \\[1st value, 2nd value\\]") -- collect server results; hitcount -- one should get all the hits, the other 0 @@ -95,6 +134,7 @@ for _, strategy in helpers.each_strategy() do ["nothashme"] = "just a value", }) assert.are.equal(requests, oks) + assert.logfile().has.line("trying to get peer with value to hash: \\[\\]") -- collect server results; hitcount -- one should get all the hits, the other 0