Skip to content

Commit cfb9a64

Browse files
authored
fix(performance): move the ipv6 check to schema validation (#12714)
1 parent 774ae2c commit cfb9a64

File tree

5 files changed

+115
-13
lines changed

5 files changed

+115
-13
lines changed

apisix/balancer.lua

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@ local set_more_tries = balancer.set_more_tries
2727
local get_last_failure = balancer.get_last_failure
2828
local set_timeouts = balancer.set_timeouts
2929
local ngx_now = ngx.now
30-
local str_byte = string.byte
3130

3231
local module_name = "balancer"
3332
local pickers = {}
@@ -195,12 +194,6 @@ end
195194
local function pick_server(route, ctx)
196195
local up_conf = ctx.upstream_conf
197196

198-
for _, node in ipairs(up_conf.nodes) do
199-
if core.utils.parse_ipv6(node.host) and str_byte(node.host, 1) ~= str_byte("[") then
200-
node.host = '[' .. node.host .. ']'
201-
end
202-
end
203-
204197
local nodes_count = #up_conf.nodes
205198
if nodes_count == 1 then
206199
local node = up_conf.nodes[1]

apisix/upstream.lua

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ local tostring = tostring
2525
local ipairs = ipairs
2626
local pairs = pairs
2727
local pcall = pcall
28+
local str_byte = string.byte
2829
local ngx_var = ngx.var
2930
local is_http = ngx.config.subsystem == "http"
3031
local upstreams
@@ -325,10 +326,16 @@ function _M.upstreams()
325326
end
326327

327328

328-
function _M.check_schema(conf)
329+
local function check_schema(conf)
330+
for _, node in ipairs(conf.nodes or {}) do
331+
if core.utils.parse_ipv6(node.host) and str_byte(node.host, 1) ~= str_byte("[") then
332+
return false, "IPv6 address must be enclosed with '[' and ']'"
333+
end
334+
end
329335
return core.schema.check(core.schema.upstream, conf)
330336
end
331337

338+
_M.check_schema = check_schema
332339

333340
local function get_chash_key_schema(hash_on)
334341
if not hash_on then
@@ -357,7 +364,7 @@ end
357364

358365
local function check_upstream_conf(in_dp, conf)
359366
if not in_dp then
360-
local ok, err = core.schema.check(core.schema.upstream, conf)
367+
local ok, err = check_schema(conf)
361368
if not ok then
362369
return false, "invalid configuration: " .. err
363370
end
@@ -396,6 +403,12 @@ local function check_upstream_conf(in_dp, conf)
396403
.. "wrong ssl type"
397404
end
398405
end
406+
else
407+
for i, node in ipairs(conf.nodes or {}) do
408+
if core.utils.parse_ipv6(node.host) and str_byte(node.host, 1) ~= str_byte("[") then
409+
conf.nodes[i].host = "[" .. node.host .. "]"
410+
end
411+
end
399412
end
400413

401414
if is_http then

t/admin/upstream.t

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -722,3 +722,33 @@ GET /t
722722
GET /t
723723
--- response_body
724724
passed
725+
726+
727+
728+
=== TEST 23: verify wrong Ipv6
729+
--- config
730+
location /t {
731+
content_by_lua_block {
732+
local core = require("apisix.core")
733+
local t = require("lib.test_admin")
734+
735+
local data = {
736+
nodes = {
737+
{host = "::1", port = 80, weight = 1},
738+
},
739+
type = "roundrobin"
740+
}
741+
local code, body = t.test('/apisix/admin/upstreams',
742+
ngx.HTTP_POST,
743+
core.json.encode(data)
744+
)
745+
746+
ngx.status = code
747+
ngx.print(body)
748+
}
749+
}
750+
--- request
751+
GET /t
752+
--- error_code: 400
753+
--- response_body
754+
{"error_msg":"invalid configuration: IPv6 address must be enclosed with '[' and ']'"}

t/core/schema_def.t

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,3 +250,69 @@ passed
250250
}
251251
--- response_body
252252
passed
253+
254+
255+
256+
=== TEST 5: validate IPv6 address format in upstream nodes
257+
--- config
258+
location /t {
259+
content_by_lua_block {
260+
local schema_def = require("apisix.schema_def")
261+
local core = require("apisix.core")
262+
local upstream = require("apisix.upstream")
263+
local t = require("lib.test_admin")
264+
-- Test valid IPv6 addresses (enclosed in brackets)
265+
local valid_cases = {
266+
{
267+
nodes = {
268+
{host = "[::1]", port = 80, weight = 1},
269+
},
270+
type = "roundrobin"
271+
},
272+
{
273+
nodes = {
274+
{host = "[2001:db8::1]", port = 80, weight = 1},
275+
},
276+
type = "roundrobin"
277+
}
278+
}
279+
280+
for _, ups in ipairs(valid_cases) do
281+
local ok, err = upstream.check_schema(ups)
282+
if not ok then
283+
ngx.log(ngx.ERR, "Expected valid case failed: ", err)
284+
end
285+
assert(ok, "Valid IPv6 case should pass: " .. (err or ""))
286+
end
287+
288+
-- Test invalid IPv6 addresses (not enclosed in brackets)
289+
local invalid_cases = {
290+
{
291+
nodes = {
292+
{host = "::1", port = 80, weight = 1},
293+
},
294+
type = "roundrobin"
295+
},
296+
{
297+
nodes = {
298+
{host = "2001:db8::1", port = 80, weight = 1},
299+
},
300+
type = "roundrobin"
301+
}
302+
}
303+
304+
for i, ups in ipairs(invalid_cases) do
305+
local ok, err = upstream.check_schema(ups)
306+
if ok then
307+
ngx.log(ngx.ERR, "Expected invalid case passed: ", i)
308+
end
309+
assert(not ok, "Invalid IPv6 case should fail")
310+
assert(string.find(err, "IPv6 address must be enclosed with '%[' and '%]'"),
311+
"Error should mention IPv6 enclosure requirement")
312+
end
313+
314+
ngx.say("passed")
315+
}
316+
}
317+
--- response_body
318+
passed

t/node/upstream-ipv6.t

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ hello world
115115
{
116116
"weight": 100,
117117
"priority": 0,
118-
"host": "::1",
118+
"host": "[::1]",
119119
"port": 1980
120120
}
121121
],
@@ -221,7 +221,7 @@ passed
221221
GET /hello
222222
--- error_code: 502
223223
--- error_log
224-
connect() to [::0.1.25.128]:80 failed
224+
failed to set server peer [::1:1980:80] err: invalid port while connecting to upstream
225225
226226
227227
@@ -237,13 +237,13 @@ connect() to [::0.1.25.128]:80 failed
237237
{
238238
"weight": 100,
239239
"priority": 0,
240-
"host": "::1",
240+
"host": "[::1]",
241241
"port": 1980
242242
},
243243
{
244244
"weight": 100,
245245
"priority": 0,
246-
"host": "::1",
246+
"host": "[::1]",
247247
"port": 1980
248248
}
249249
],

0 commit comments

Comments
 (0)