You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@apisix.apache.org by me...@apache.org on 2020/08/30 14:43:36 UTC
[apisix] branch master updated: feat: support different modes to
pass host to upstream (#2132)
This is an automated email from the ASF dual-hosted git repository.
membphis pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/apisix.git
The following commit(s) were added to refs/heads/master by this push:
new 502310b feat: support different modes to pass host to upstream (#2132)
502310b is described below
commit 502310bef6c6b77410e17bf3b805437fe4c705f9
Author: nic-chen <33...@users.noreply.github.com>
AuthorDate: Sun Aug 30 22:43:28 2020 +0800
feat: support different modes to pass host to upstream (#2132)
* test: using `httpbin.org` for test cases.
* doc: add doc
* remove golang apt repository and runtime in travis.
* download proto file
Co-authored-by: Yuansheng <me...@gmail.com>
---
.travis/linux_apisix_current_luarocks_runner.sh | 1 -
.travis/linux_apisix_master_luarocks_runner.sh | 1 -
.travis/linux_openresty_mtls_runner.sh | 1 -
.travis/linux_openresty_runner.sh | 3 -
.travis/linux_tengine_runner.sh | 3 -
.travis/osx_openresty_runner.sh | 2 -
apisix/admin/upstreams.lua | 13 +++
apisix/init.lua | 43 ++++++++
apisix/schema_def.lua | 7 ++
doc/admin-api.md | 3 +
doc/architecture-design.md | 2 +
doc/zh-cn/admin-api.md | 2 +
doc/zh-cn/architecture-design.md | 2 +
t/admin/routes.t | 33 ++++++
t/admin/upstream.t | 59 ++++++++++
t/node/merge-route.t | 3 +-
t/node/route-domain.t | 90 +++++++++++++++
t/node/upstream.t | 141 ++++++++++++++++++++++++
18 files changed, 396 insertions(+), 13 deletions(-)
diff --git a/.travis/linux_apisix_current_luarocks_runner.sh b/.travis/linux_apisix_current_luarocks_runner.sh
index 0264fc5..5a48932 100755
--- a/.travis/linux_apisix_current_luarocks_runner.sh
+++ b/.travis/linux_apisix_current_luarocks_runner.sh
@@ -27,7 +27,6 @@ do_install() {
sudo apt-get -y update --fix-missing
sudo apt-get -y install software-properties-common
sudo add-apt-repository -y "deb http://openresty.org/package/ubuntu $(lsb_release -sc) main"
- sudo add-apt-repository -y ppa:longsleep/golang-backports
sudo apt-get update
sudo apt-get install openresty-debug lua5.1 liblua5.1-0-dev
diff --git a/.travis/linux_apisix_master_luarocks_runner.sh b/.travis/linux_apisix_master_luarocks_runner.sh
index 6b63f3a..a7b684c 100755
--- a/.travis/linux_apisix_master_luarocks_runner.sh
+++ b/.travis/linux_apisix_master_luarocks_runner.sh
@@ -28,7 +28,6 @@ do_install() {
sudo apt-get -y update --fix-missing
sudo apt-get -y install software-properties-common
sudo add-apt-repository -y "deb http://openresty.org/package/ubuntu $(lsb_release -sc) main"
- sudo add-apt-repository -y ppa:longsleep/golang-backports
sudo apt-get update
sudo apt-get install openresty-debug lua5.1 liblua5.1-0-dev
diff --git a/.travis/linux_openresty_mtls_runner.sh b/.travis/linux_openresty_mtls_runner.sh
index d0a7ceb..876c868 100755
--- a/.travis/linux_openresty_mtls_runner.sh
+++ b/.travis/linux_openresty_mtls_runner.sh
@@ -44,7 +44,6 @@ do_install() {
sudo apt-get -y update --fix-missing
sudo apt-get -y install software-properties-common
sudo add-apt-repository -y "deb http://openresty.org/package/ubuntu $(lsb_release -sc) main"
- sudo add-apt-repository -y ppa:longsleep/golang-backports
sudo apt-get update
sudo apt-get install openresty-debug lua5.1 liblua5.1-0-dev
diff --git a/.travis/linux_openresty_runner.sh b/.travis/linux_openresty_runner.sh
index 6cc48b4..42ff254 100755
--- a/.travis/linux_openresty_runner.sh
+++ b/.travis/linux_openresty_runner.sh
@@ -59,7 +59,6 @@ do_install() {
sudo apt-get -y update --fix-missing
sudo apt-get -y install software-properties-common
sudo add-apt-repository -y "deb http://openresty.org/package/ubuntu $(lsb_release -sc) main"
- sudo add-apt-repository -y ppa:longsleep/golang-backports
sudo apt-get update
sudo apt-get install openresty-debug lua5.1 liblua5.1-0-dev
@@ -75,8 +74,6 @@ do_install() {
sudo luarocks install luacheck > build.log 2>&1 || (cat build.log && exit 1)
- export GO111MOUDULE=on
-
if [ ! -f "build-cache/apisix-master-0.rockspec" ]; then
create_lua_deps
diff --git a/.travis/linux_tengine_runner.sh b/.travis/linux_tengine_runner.sh
index ec73c16..2404978 100755
--- a/.travis/linux_tengine_runner.sh
+++ b/.travis/linux_tengine_runner.sh
@@ -228,7 +228,6 @@ do_install() {
sudo apt-get -y update --fix-missing
sudo apt-get -y install software-properties-common
- sudo add-apt-repository -y ppa:longsleep/golang-backports
sudo apt-get update
sudo apt-get install lua5.1 liblua5.1-0-dev
@@ -244,8 +243,6 @@ do_install() {
cd ..
rm -rf luarocks-2.4.4
- export GO111MOUDULE=on
-
if [ ! -f "build-cache/apisix-master-0.rockspec" ]; then
create_lua_deps
diff --git a/.travis/osx_openresty_runner.sh b/.travis/osx_openresty_runner.sh
index b31e9de..6070f02 100755
--- a/.travis/osx_openresty_runner.sh
+++ b/.travis/osx_openresty_runner.sh
@@ -28,12 +28,10 @@ before_install() {
fi
HOMEBREW_NO_AUTO_UPDATE=1 brew install perl cpanminus etcd luarocks openresty/brew/openresty-debug redis@3.2
- brew upgrade go
sudo sed -i "" "s/requirepass/#requirepass/g" /usr/local/etc/redis.conf
brew services start redis@3.2
- export GO111MOUDULE=on
sudo cpanm --notest Test::Nginx >build.log 2>&1 || (cat build.log && exit 1)
export_or_prefix
luarocks install --lua-dir=${OPENRESTY_PREFIX}/luajit luacov-coveralls --local --tree=deps
diff --git a/apisix/admin/upstreams.lua b/apisix/admin/upstreams.lua
index b74f46e..8f03e89 100644
--- a/apisix/admin/upstreams.lua
+++ b/apisix/admin/upstreams.lua
@@ -54,6 +54,18 @@ local function check_upstream_conf(conf)
return false, "invalid configuration: " .. err
end
+ if conf.pass_host == "node" and conf.nodes and
+ core.table.nkeys(conf.nodes) ~= 1
+ then
+ return false, "only support single node for `node` mode currently"
+ end
+
+ if conf.pass_host == "rewrite" and
+ (conf.upstream_host == nil or conf.upstream_host == "")
+ then
+ return false, "`upstream_host` can't be empty when `pass_host` is `rewrite`"
+ end
+
if conf.type ~= "chash" then
return true
end
@@ -77,6 +89,7 @@ local function check_upstream_conf(conf)
return false, "invalid configuration: " .. err
end
end
+
return true
end
diff --git a/apisix/init.lua b/apisix/init.lua
index 3a69534..6e20cfd 100644
--- a/apisix/init.lua
+++ b/apisix/init.lua
@@ -203,6 +203,7 @@ local function parse_domain_for_nodes(nodes)
if ip then
local new_node = core.table.clone(node)
new_node.host = ip
+ new_node.domain = host
core.table.insert(new_nodes, new_node)
end
@@ -297,6 +298,36 @@ local function return_direct(...)
end
+local function set_upstream_host(api_ctx)
+ local pass_host = api_ctx.pass_host or "pass"
+ if pass_host == "pass" then
+ return
+ end
+
+ if pass_host == "rewrite" then
+ api_ctx.var.upstream_host = api_ctx.upstream_host
+ return
+ end
+
+ -- only support single node for `node` mode currently
+ local host
+ local up_conf = api_ctx.upstream_conf
+ local nodes_count = up_conf.nodes and #up_conf.nodes or 0
+ if nodes_count == 1 then
+ local node = up_conf.nodes[1]
+ if node.domain and #node.domain > 0 then
+ host = node.domain
+ else
+ host = node.host
+ end
+ end
+
+ if host then
+ api_ctx.var.upstream_host = host
+ end
+end
+
+
function _M.http_access_phase()
local ngx_ctx = ngx.ctx
local api_ctx = ngx_ctx.api_ctx
@@ -429,6 +460,11 @@ function _M.http_access_phase()
if upstream.value.enable_websocket then
enable_websocket = true
end
+
+ if upstream.value.pass_host then
+ api_ctx.pass_host = upstream.value.pass_host
+ api_ctx.upstream_host = upstream.value.upstream_host
+ end
end
else
@@ -455,6 +491,11 @@ function _M.http_access_phase()
if route.value.upstream and route.value.upstream.enable_websocket then
enable_websocket = true
end
+
+ if route.value.upstream and route.value.upstream.pass_host then
+ api_ctx.pass_host = route.value.upstream.pass_host
+ api_ctx.upstream_host = route.value.upstream.upstream_host
+ end
end
if enable_websocket then
@@ -490,6 +531,8 @@ function _M.http_access_phase()
core.log.error("failed to parse upstream: ", err)
core.response.exit(500)
end
+
+ set_upstream_host(api_ctx)
end
diff --git a/apisix/schema_def.lua b/apisix/schema_def.lua
index a6656b2..52a7f42 100644
--- a/apisix/schema_def.lua
+++ b/apisix/schema_def.lua
@@ -332,6 +332,13 @@ local upstream_schema = {
description = "enable websocket for request",
type = "boolean"
},
+ pass_host = {
+ description = "mod of host passing",
+ type = "string",
+ enum = {"pass", "node", "rewrite"},
+ default = "pass"
+ },
+ upstream_host = host_def,
name = {type = "string", maxLength = 50},
desc = {type = "string", maxLength = 256},
service_name = {type = "string", maxLength = 50},
diff --git a/doc/admin-api.md b/doc/admin-api.md
index 3b8ac89..e197421 100644
--- a/doc/admin-api.md
+++ b/doc/admin-api.md
@@ -504,6 +504,9 @@ In addition to the basic complex equalization algorithm selection, APISIX's Upst
|timeout|optional| Set the timeout for connection, sending and receiving messages. |
|name |optional|Identifies upstream names|
|desc |optional|upstream usage scenarios, and more.|
+|pass_host |optional|`pass` pass the client request host, `node` not pass the client request host, using the upstream node host, `rewrite` rewrite host by the configured `upstream_host`.|
+|upstream_host |optional|This option is only valid if the `pass_host` is `rewrite`.|
+
Config Example:
diff --git a/doc/architecture-design.md b/doc/architecture-design.md
index a8593b8..34a8af8 100644
--- a/doc/architecture-design.md
+++ b/doc/architecture-design.md
@@ -265,6 +265,8 @@ In addition to the basic complex equalization algorithm selection, APISIX's Upst
|enable_websocket|optional| enable `websocket`(boolean), default `false`.|
|timeout|optional| Set the timeout for connection, sending and receiving messages. |
|desc |optional|Identifies route names, usage scenarios, and more.|
+|pass_host |optional|`pass` pass the client request host, `node` not pass the client request host, using the upstream node host, `rewrite` rewrite host by the configured `upstream_host`.|
+|upstream_host |optional|This option is only valid if the `pass_host` is `rewrite`.|
Create an upstream object use case:
diff --git a/doc/zh-cn/admin-api.md b/doc/zh-cn/admin-api.md
index 529d102..0597ef9 100644
--- a/doc/zh-cn/admin-api.md
+++ b/doc/zh-cn/admin-api.md
@@ -518,6 +518,8 @@ APISIX 的 Upstream 除了基本的复杂均衡算法选择外,还支持对上
|hash_on |可选 |辅助|该参数作为一致性 hash 的入参||
|name |可选 |辅助|标识上游服务名称、使用场景等。||
|desc |可选 |辅助|上游服务描述、使用场景等。||
+|pass_host |可选|枚举|`pass` 透传客户端请求的 host, `node` 不透传客户端请求的 host, 使用 upstream node 配置的 host, `rewrite` 使用 `upstream_host` 配置的值重写 host 。||
+|upstream_host |可选|辅助|只在 `pass_host` 配置为 `rewrite` 时有效。||
upstream 对象 json 配置内容:
diff --git a/doc/zh-cn/architecture-design.md b/doc/zh-cn/architecture-design.md
index 37ff449..0b5eabf 100644
--- a/doc/zh-cn/architecture-design.md
+++ b/doc/zh-cn/architecture-design.md
@@ -273,6 +273,8 @@ APISIX 的 Upstream 除了基本的复杂均衡算法选择外,还支持对上
|checks |可选|配置健康检查的参数,详细可参考[health-check](../health-check.md)|
|retries |可选|使用底层的 Nginx 重试机制将请求传递给下一个上游,默认 APISIX 会启用重试机制,根据配置的后端节点个数设置重试次数,如果此参数显式被设置将会覆盖系统默认设置的重试次数。|
|enable_websocket|可选| 是否启用 `websocket`(布尔值),默认不启用|
+|pass_host |可选|`pass` 透传客户端请求的 host, `node` 不透传客户端请求的 host, 使用 upstream node 配置的 host, `rewrite` 使用 `upstream_host` 配置的值重写 host 。|
+|upstream_host |可选|只在 `pass_host` 配置为 `rewrite` 时有效。|
`hash_on` 比较复杂,这里专门说明下:
diff --git a/t/admin/routes.t b/t/admin/routes.t
index afa846a..9d98b25 100644
--- a/t/admin/routes.t
+++ b/t/admin/routes.t
@@ -2147,3 +2147,36 @@ GET /t
{"error_msg":"invalid configuration: value wasn't supposed to match schema"}
--- no_error_log
[error]
+
+
+
+=== TEST 59: invalid route: multi nodes with `node` mode to pass host
+--- config
+ location /t {
+ content_by_lua_block {
+ local t = require("lib.test_admin").test
+ local code, body = t('/apisix/admin/routes/1',
+ ngx.HTTP_PUT,
+ [[{
+ "methods": ["GET", "GET"],
+ "upstream": {
+ "nodes": {
+ "httpbin.org:8080": 1,
+ "test.com:8080": 1
+ },
+ "type": "roundrobin",
+ "pass_host": "node"
+ },
+ "uri": "/index.html"
+ }]]
+ )
+
+ ngx.status = code
+ ngx.print(body)
+ }
+ }
+--- request
+GET /t
+--- error_code: 400
+--- no_error_log
+[error]
diff --git a/t/admin/upstream.t b/t/admin/upstream.t
index 02cd5e0..3dc116d 100644
--- a/t/admin/upstream.t
+++ b/t/admin/upstream.t
@@ -1578,3 +1578,62 @@ GET /t
{"error_msg":"invalid configuration: property \"retries\" validation failed: expected -1 to be greater than 0"}
--- no_error_log
[error]
+
+
+
+=== TEST 48: invalid route: multi nodes with `node` mode to pass host
+--- 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": {
+ "httpbin.org:8080": 1,
+ "test.com:8080": 1
+ },
+ "type": "roundrobin",
+ "pass_host": "node"
+ }]]
+ )
+
+ ngx.status = code
+ ngx.print(body)
+ }
+ }
+--- request
+GET /t
+--- error_code: 400
+--- no_error_log
+[error]
+
+
+
+=== TEST 49: invalid route: empty `upstream_host` when `pass_host` is `rewrite`
+--- 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": {
+ "httpbin.org:8080": 1,
+ "test.com:8080": 1
+ },
+ "type": "roundrobin",
+ "pass_host": "rewrite",
+ "upstream_host": ""
+ }]]
+ )
+
+ ngx.status = code
+ ngx.print(body)
+ }
+ }
+--- request
+GET /t
+--- error_code: 400
+--- no_error_log
+[error]
diff --git a/t/node/merge-route.t b/t/node/merge-route.t
index 772ab0d..988699a 100644
--- a/t/node/merge-route.t
+++ b/t/node/merge-route.t
@@ -280,8 +280,7 @@ passed
"host": "httpbin.org",
"plugins": {
"proxy-rewrite": {
- "scheme": "https"
-
+ "scheme": "https"
}
},
"service_id": "1"
diff --git a/t/node/route-domain.t b/t/node/route-domain.t
index 05bc3d9..6fbd31d 100644
--- a/t/node/route-domain.t
+++ b/t/node/route-domain.t
@@ -80,3 +80,93 @@ hello world
[error]
--- error_log eval
qr/dns resolver domain: baidu.com to \d+.\d+.\d+.\d+/
+
+
+
+=== TEST 4: set route(id: 1, using `rewrite` mode to pass upstream host)
+--- config
+ location /t {
+ content_by_lua_block {
+ local t = require("lib.test_admin").test
+ local code, body = t('/apisix/admin/routes/1',
+ ngx.HTTP_PUT,
+ [[{
+ "upstream": {
+ "nodes": {
+ "127.0.0.1:1980": 1
+ },
+ "type": "roundrobin",
+ "pass_host": "rewrite",
+ "upstream_host": "httpbin.org"
+ },
+ "uri": "/uri"
+ }]]
+ )
+
+ if code >= 300 then
+ ngx.status = code
+ end
+ ngx.say(body)
+ }
+ }
+--- request
+GET /t
+--- response_body
+passed
+--- no_error_log
+[error]
+
+
+
+=== TEST 5: hit route
+--- request
+GET /uri
+--- response_body eval
+qr/host: httpbin.org/
+--- no_error_log
+[error]
+
+
+
+=== TEST 6: set route(id: 1, using `node` mode to pass upstream host)
+--- config
+ location /t {
+ content_by_lua_block {
+ local t = require("lib.test_admin").test
+ local code, body = t('/apisix/admin/routes/1',
+ ngx.HTTP_PUT,
+ [[{
+ "upstream": {
+ "nodes": {
+ "httpbin.org:80": 1
+ },
+ "type": "roundrobin",
+ "desc": "new upstream",
+ "pass_host": "node"
+ },
+ "uri": "/get"
+ }]]
+ )
+
+ if code >= 300 then
+ ngx.status = code
+ end
+ ngx.say(body)
+ }
+ }
+--- request
+GET /t
+--- response_body
+passed
+--- no_error_log
+[error]
+
+
+
+=== TEST 7: hit route
+--- request
+GET /get
+--- response_body eval
+qr/"Host": "httpbin.org"/
+--- no_error_log
+[error]
diff --git a/t/node/upstream.t b/t/node/upstream.t
index f631971..ef88bbd 100644
--- a/t/node/upstream.t
+++ b/t/node/upstream.t
@@ -262,3 +262,144 @@ GET /t
[delete] code: 404
--- no_error_log
[error]
+
+
+
+=== TEST 11: set upstream(id: 1, using `node` mode to pass upstream host)
+--- 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": {
+ "httpbin.org:80": 1
+ },
+ "type": "roundrobin",
+ "desc": "new upstream",
+ "pass_host": "node"
+ }]]
+ )
+
+ if code >= 300 then
+ ngx.status = code
+ end
+ ngx.say(body)
+ }
+ }
+--- request
+GET /t
+--- response_body
+passed
+--- no_error_log
+[error]
+
+
+
+=== TEST 12: set route(id: 1, using `node` mode to pass upstream host)
+--- config
+ location /t {
+ content_by_lua_block {
+ local t = require("lib.test_admin").test
+ local code, body = t('/apisix/admin/routes/1',
+ ngx.HTTP_PUT,
+ [[{
+ "uri": "/get",
+ "upstream_id": "1"
+ }]]
+ )
+
+ if code >= 300 then
+ ngx.status = code
+ end
+ ngx.say(body)
+ }
+ }
+--- request
+GET /t
+--- response_body
+passed
+--- no_error_log
+[error]
+
+
+
+=== TEST 13: hit route
+--- request
+GET /get
+--- response_body eval
+qr/"Host": "httpbin.org"/
+--- no_error_log
+[error]
+
+
+
+=== TEST 14: set upstream(id: 1, using `rewrite` mode to pass upstream host)
+--- 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:1980": 1
+ },
+ "type": "roundrobin",
+ "desc": "new upstream",
+ "pass_host": "rewrite",
+ "upstream_host": "httpbin.org"
+ }]]
+ )
+
+ if code >= 300 then
+ ngx.status = code
+ end
+ ngx.say(body)
+ }
+ }
+--- request
+GET /t
+--- response_body
+passed
+--- no_error_log
+[error]
+
+
+
+=== TEST 15: set route(id: 1, using `rewrite` mode to pass upstream host)
+--- config
+ location /t {
+ content_by_lua_block {
+ local t = require("lib.test_admin").test
+ local code, body = t('/apisix/admin/routes/1',
+ ngx.HTTP_PUT,
+ [[{
+ "uri": "/uri",
+ "upstream_id": "1"
+ }]]
+ )
+
+ if code >= 300 then
+ ngx.status = code
+ end
+ ngx.say(body)
+ }
+ }
+--- request
+GET /t
+--- response_body
+passed
+--- no_error_log
+[error]
+
+
+
+=== TEST 16: hit route
+--- request
+GET /uri
+--- response_body eval
+qr/host: httpbin.org/
+--- no_error_log
+[error]