From 435565d322a4533e173234e79fb63cd7cf066956 Mon Sep 17 00:00:00 2001 From: LetsGO Date: Wed, 18 May 2022 13:02:18 +0800 Subject: [PATCH] fix: redirect http to https but port not change (#7065) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Wei Jiang Co-authored-by: 罗泽轩 Co-authored-by: tzssangglass Co-authored-by: Alex Zhang --- apisix/plugins/redirect.lua | 41 +++++++++++++++++++- conf/config-default.yaml | 2 + docs/en/latest/plugins/redirect.md | 5 ++- docs/zh/latest/plugins/redirect.md | 5 ++- t/plugin/redirect.t | 61 ++++++++++++++++++++---------- 5 files changed, 90 insertions(+), 24 deletions(-) diff --git a/apisix/plugins/redirect.lua b/apisix/plugins/redirect.lua index 104cf9d45d48..6c9a99a1575c 100644 --- a/apisix/plugins/redirect.lua +++ b/apisix/plugins/redirect.lua @@ -15,6 +15,7 @@ -- limitations under the License. -- local core = require("apisix.core") +local plugin = require("apisix.plugin") local tab_insert = table.insert local tab_concat = table.concat local string_format = string.format @@ -24,7 +25,8 @@ local ipairs = ipairs local ngx = ngx local str_find = core.string.find local str_sub = string.sub -local tonumber = tonumber +local type = type +local math_random = math.random local lrucache = core.lrucache.new({ ttl = 300, count = 100 @@ -143,12 +145,47 @@ local function concat_new_uri(uri, ctx) return tab_concat(tmp, "") end +local function get_port(attr) + local port + if attr then + port = attr.https_port + end + + if port then + return port + end + + local local_conf = core.config.local_conf() + local ssl = core.table.try_read_attr(local_conf, "apisix", "ssl") + if not ssl or not ssl["enable"] then + return port + end + + port = ssl["listen_port"] + if port then + return port + end + + local ports = ssl["listen"] + if ports and #ports > 0 then + local idx = math_random(1, #ports) + port = ports[idx] + if type(port) == "table" then + port = port.port + end + end + + return port +end function _M.rewrite(conf, ctx) core.log.info("plugin rewrite phase, conf: ", core.json.delay_encode(conf)) local ret_code = conf.ret_code - local ret_port = tonumber(ctx.var["var_x_forwarded_port"]) + + local attr = plugin.plugin_attr(plugin_name) + local ret_port = get_port(attr) + local uri = conf.uri local regex_uri = conf.regex_uri diff --git a/conf/config-default.yaml b/conf/config-default.yaml index bdf445545037..f60c6577fc79 100644 --- a/conf/config-default.yaml +++ b/conf/config-default.yaml @@ -470,3 +470,5 @@ plugin_attr: connect: 60s read: 60s send: 60s +# redirect: +# https_port: 8443 # the default port for use by HTTP redirects to HTTPS diff --git a/docs/en/latest/plugins/redirect.md b/docs/en/latest/plugins/redirect.md index 865ef602d3e6..8a7a034bc934 100644 --- a/docs/en/latest/plugins/redirect.md +++ b/docs/en/latest/plugins/redirect.md @@ -45,7 +45,10 @@ The `redirect` Plugin can be used to configure redirects. Only one of `http_to_https`, `uri` and `regex_uri` can be configured. -* When enabling `http_to_https`, the port in the redirect URL will be the value of header `X-Forwarded-Port` or the port of the server. +* When enabling `http_to_https`, the ports in the redirect URL will pick a value in the following order (in descending order of priority) + * Read `plugin_attr.redirect.https_port` from the configuration file (`conf/config.yaml`). + * If `apisix.ssl` is enabled, read `apisix.ssl.listen_port` first, and if it does not exist, read `apisix.ssl.listen` and select a port randomly from it. + * Use 443 as the default https port. ::: diff --git a/docs/zh/latest/plugins/redirect.md b/docs/zh/latest/plugins/redirect.md index 75ece0243e4e..276132b48aa5 100644 --- a/docs/zh/latest/plugins/redirect.md +++ b/docs/zh/latest/plugins/redirect.md @@ -45,7 +45,10 @@ description: 本文介绍了关于 Apache APISIX `redirect` 插件的基本信 `http_to_https`、`uri` 和 `regex_uri` 只能配置其中一个属性。 -* 当开启 `http_to_https` 时,重定向 URL 中的端口将是 `X-Forwarded-Port` 请求头的值或服务器的端口。 +* 当开启 `http_to_https` 时,重定向 URL 中的端口将按如下顺序选取一个值(按优先级从高到低排列) + * 从配置文件(`conf/config.yaml`)中读取 `plugin_attr.redirect.https_port`。 + * 如果 `apisix.ssl` 处于开启状态,先读取 `apisix.ssl.listen_port`,如果没有,再读取 `apisix.ssl.listen` 并从中随机选一个 `port`。 + * 使用 443 作为默认 `https port`。 ::: diff --git a/t/plugin/redirect.t b/t/plugin/redirect.t index 47479a2b468e..3b8d87afd787 100644 --- a/t/plugin/redirect.t +++ b/t/plugin/redirect.t @@ -428,59 +428,80 @@ passed -=== TEST 18: redirect +=== TEST 18: redirect(port using `plugin_attr.redirect.https_port`) +--- extra_yaml_config +plugin_attr: + redirect: + https_port: 8443 --- request GET /hello --- more_headers Host: foo.com --- error_code: 301 --- response_headers -Location: https://foo.com:1984/hello +Location: https://foo.com:8443/hello -=== TEST 19: redirect(pass well-known port 443 to x-forwarded-port) +=== TEST 19: redirect(port using `apisix.ssl.listen_port`) +--- yaml_config +apisix: + ssl: + enable: true + listen_port: 9445 --- request GET /hello --- more_headers Host: foo.com -x-forwarded-port: 443 --- error_code: 301 --- response_headers -Location: https://foo.com/hello +Location: https://foo.com:9445/hello -=== TEST 20: redirect(pass negative number to x-forwarded-port) +=== TEST 20: redirect(port using `apisix.ssl.listen` when listen length is one) --- request GET /hello --- more_headers Host: foo.com -x-forwarded-port: -443 --- error_code: 301 --- response_headers -Location: https://foo.com/hello +Location: https://foo.com:9443/hello -=== TEST 21: redirect(pass number more than 65535 to x-forwarded-port) +=== TEST 21: redirect(port using `apisix.ssl.listen` when listen length more than one) +--- yaml_config +apisix: + ssl: + enable: true + listen: + - 6443 + - 7443 + - port: 8443 + - port: 9443 --- request GET /hello --- more_headers Host: foo.com -x-forwarded-port: 65536 --- error_code: 301 ---- response_headers -Location: https://foo.com/hello +--- response_headers_like +Location: https://foo.com:[6-9]443/hello -=== TEST 22: redirect(pass invalid non-number to x-forwarded-port) +=== TEST 22: redirect(port using `https default port`) +--- yaml_config +apisix: + ssl: + enable: null +--- extra_yaml_config +plugin_attr: + redirect: null --- request GET /hello --- more_headers Host: foo.com -x-forwarded-port: ok --- error_code: 301 --- response_headers Location: https://foo.com/hello @@ -528,7 +549,7 @@ GET /hello Host: foo.com --- error_code: 301 --- response_headers -Location: https://foo.com:1984/hello +Location: https://foo.com:9443/hello @@ -613,7 +634,7 @@ GET /hello Host: test.com --- error_code: 301 --- response_headers -Location: https://test.com:1984/hello +Location: https://test.com:9443/hello @@ -763,7 +784,7 @@ POST /hello-https --- more_headers Host: test.com --- response_headers -Location: https://test.com:1984/hello-https +Location: https://test.com:9443/hello-https --- error_code: 308 --- no_error_log [error] @@ -776,7 +797,7 @@ GET /hello-https --- more_headers Host: test.com --- response_headers -Location: https://test.com:1984/hello-https +Location: https://test.com:9443/hello-https --- error_code: 301 --- no_error_log [error] @@ -789,7 +810,7 @@ HEAD /hello-https --- more_headers Host: test.com --- response_headers -Location: https://test.com:1984/hello-https +Location: https://test.com:9443/hello-https --- error_code: 301 --- no_error_log [error] @@ -1092,4 +1113,4 @@ Host: foo.com X-Forwarded-Proto: http --- error_code: 301 --- response_headers -Location: https://foo.com:1984/hello +Location: https://foo.com:9443/hello