feat: support for having port in host header when pass_host = node and port is not standard (#6600)

Co-authored-by: spacewander <spacewanderlzx@gmail.com>
This commit is contained in:
zenghuilin 2022-03-18 16:08:15 +08:00 committed by GitHub
parent 003b89d39c
commit c7755543ae
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 190 additions and 65 deletions

View File

@ -18,6 +18,7 @@ local require = require
local balancer = require("ngx.balancer")
local core = require("apisix.core")
local priority_balancer = require("apisix.balancer.priority")
local apisix_upstream = require("apisix.upstream")
local ipairs = ipairs
local is_http = ngx.config.subsystem == "http"
local enable_keepalive = balancer.enable_keepalive and is_http
@ -176,6 +177,16 @@ local function set_balancer_opts(route, ctx)
end
local function parse_server_for_upstream_host(picked_server, upstream_scheme)
local standard_port = apisix_upstream.scheme_to_port[upstream_scheme]
local host = picked_server.domain or picked_server.host
if upstream_scheme and (not standard_port or standard_port ~= picked_server.port) then
host = host .. ":" .. picked_server.port
end
return host
end
-- pick_server will be called:
-- 1. in the access phase so that we can set headers according to the picked server
-- 2. each time we need to retry upstream
@ -189,6 +200,7 @@ local function pick_server(route, ctx)
local node = up_conf.nodes[1]
ctx.balancer_ip = node.host
ctx.balancer_port = node.port
node.upstream_host = parse_server_for_upstream_host(node, ctx.upstream_scheme)
return node
end
@ -250,6 +262,7 @@ local function pick_server(route, ctx)
ctx.balancer_ip = res.host
ctx.balancer_port = res.port
ctx.server_picker = server_picker
res.upstream_host = parse_server_for_upstream_host(res, ctx.upstream_scheme)
return res
end
@ -331,7 +344,7 @@ function _M.run(route, ctx, plugin_funcs)
local header_changed
local pass_host = ctx.pass_host
if pass_host == "node" and balancer.recreate_request then
local host = server.domain or server.host
local host = server.upstream_host
if host ~= ctx.var.upstream_host then
-- retried node has a different host
ctx.var.upstream_host = host

View File

@ -257,11 +257,8 @@ local function set_upstream_host(api_ctx, picked_server)
end
local nodes_count = up_conf.nodes and #up_conf.nodes or 0
if nodes_count == 1 then
local node = up_conf.nodes[1]
api_ctx.var.upstream_host = node.domain or node.host
elseif picked_server.domain and ngx_balancer.recreate_request then
api_ctx.var.upstream_host = picked_server.domain
if nodes_count == 1 or ngx_balancer.recreate_request then
api_ctx.var.upstream_host = picked_server.upstream_host
end
end

View File

@ -165,8 +165,6 @@ local function set_upstream_scheme(ctx, upstream)
end
local fill_node_info
do
local scheme_to_port = {
http = 80,
https = 443,
@ -174,7 +172,11 @@ do
grpcs = 443,
}
function fill_node_info(up_conf, scheme, is_stream)
_M.scheme_to_port = scheme_to_port
local function fill_node_info(up_conf, scheme, is_stream)
local nodes = up_conf.nodes
if up_conf.nodes_ref == nodes then
-- filled
@ -227,7 +229,6 @@ do
up_conf.nodes = filled_nodes
return true
end
end
function _M.set_by_route(route, api_ctx)

View File

@ -209,14 +209,14 @@ sleep 4
tail -n 2 logs/access.log > output.log
# APISIX
if ! grep '"https://localhost" -' output.log; then
if ! grep '"https://localhost:9180" -' output.log; then
echo "failed: should find upstream scheme"
cat output.log
exit 1
fi
# admin
if ! grep '"http://localhost" localhost' output.log; then
if ! grep '"http://localhost:9180" localhost' output.log; then
echo "failed: should find upstream scheme"
cat output.log
exit 1

View File

@ -258,5 +258,5 @@ host: www.sni.com
Receive SNI: localhost
--- response_body
uri: /uri
host: localhost
host: localhost:1983
x-real-ip: 127.0.0.1

114
t/node/upstream.t vendored
View File

@ -510,3 +510,117 @@ GET /uri
qr/host: localhost/
--- error_log
proxy request to 127.0.0.1:1980
=== TEST 21: check that including port in host header is supported when pass_host = node and port is not standard
--- config
location /t {
content_by_lua_block {
local t = require("lib.test_admin").test
local code, body = t('/apisix/admin/upstreams/1',
ngx.HTTP_PUT,
[[{
"nodes": {
"localhost:1980": 1000
},
"type": "roundrobin",
"pass_host": "node"
}]]
)
if code >= 300 then
ngx.status = code
ngx.say(body)
return
end
local code, body = t('/apisix/admin/routes/1',
ngx.HTTP_PUT,
[[{
"methods": ["GET"],
"upstream_id": "1",
"uri": "/uri"
}]]
)
if code >= 300 then
ngx.status = code
end
ngx.say(body)
}
}
--- request
GET /t
--- response_body
passed
--- no_error_log
[error]
=== TEST 22: hit route
--- request
GET /uri
--- response_body eval
qr/host: localhost:1980/
--- no_error_log
[error]
=== TEST 23: check that including port in host header is supported when retrying and pass_host = node and port is not standard
--- config
location /t {
content_by_lua_block {
local t = require("lib.test_admin").test
local code, body = t('/apisix/admin/upstreams/1',
ngx.HTTP_PUT,
[[{
"nodes": {
"127.0.0.1:1979": 1000,
"localhost:1980": 1
},
"type": "roundrobin",
"pass_host": "node"
}]]
)
if code >= 300 then
ngx.status = code
ngx.say(body)
return
end
local code, body = t('/apisix/admin/routes/1',
ngx.HTTP_PUT,
[[{
"methods": ["GET"],
"upstream_id": "1",
"uri": "/uri"
}]]
)
if code >= 300 then
ngx.status = code
end
ngx.say(body)
}
}
--- skip_nginx: 5: < 1.19.0
--- request
GET /t
--- response_body
passed
--- no_error_log
[error]
=== TEST 24: hit route
--- log_level: debug
--- skip_nginx: 5: < 1.19.0
--- request
GET /uri
--- error_log
Host: 127.0.0.1:1979