diff --git a/apisix/cli/ops.lua b/apisix/cli/ops.lua index 36ea47af3eb8..e7f86f562e22 100644 --- a/apisix/cli/ops.lua +++ b/apisix/cli/ops.lua @@ -185,12 +185,9 @@ local function init(env) local checked_admin_key = false local allow_admin = yaml_conf.deployment.admin and yaml_conf.deployment.admin.allow_admin - if yaml_conf.apisix.enable_admin and allow_admin then - for _, allow_ip in ipairs(allow_admin) do - if allow_ip == "127.0.0.0/24" then - checked_admin_key = true - end - end + if yaml_conf.apisix.enable_admin and allow_admin + and #allow_admin == 1 and allow_admin[1] == "127.0.0.0/24" then + checked_admin_key = true end if yaml_conf.apisix.enable_admin and not checked_admin_key then diff --git a/apisix/core/config_util.lua b/apisix/core/config_util.lua index 4cc0ed33daf3..7e57ed402fd8 100644 --- a/apisix/core/config_util.lua +++ b/apisix/core/config_util.lua @@ -88,8 +88,14 @@ function _M.cancel_clean_handler(item, idx, fire) end core_tab.remove(item.clean_handlers, pos) - if fire then + if not fire then + return + end + + if f then f(item) + else + log.error("The function used to clear the health checker is nil, please check") end end diff --git a/apisix/core/utils.lua b/apisix/core/utils.lua index 01c8b34c8503..70531e7c1fa9 100644 --- a/apisix/core/utils.lua +++ b/apisix/core/utils.lua @@ -335,4 +335,45 @@ end _M.resolve_var = resolve_var +local resolve_var_with_captures +do + local _captures + -- escape is not supported very well, like there is a redundant '\' after escape "$1" + local pat = [[ (? conf/config.yaml + +make init > output.log 2>&1 | true + +if grep -E "ERROR: missing valid Admin API token." output.log > /dev/null; then + echo "failed: should not show 'ERROR: missing valid Admin API token.'" + exit 1 +fi + +echo ' +deployment: + admin: + admin_key: ~ + allow_admin: + - 0.0.0.0/0 + - 127.0.0.0/24 +' > conf/config.yaml + +make init > output.log 2>&1 | true + +if ! grep -E "ERROR: missing valid Admin API token." output.log > /dev/null; then + echo "failed: should show 'ERROR: missing valid Admin API token.'" + exit 1 +fi + +echo "pass: missing admin key and only allow 127.0.0.0/24 to access admin api" + # admin api, allow any IP but use default key echo ' diff --git a/t/node/healthcheck3.t b/t/node/healthcheck3.t new file mode 100644 index 000000000000..a1209afa9f7b --- /dev/null +++ b/t/node/healthcheck3.t @@ -0,0 +1,122 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +use t::APISIX 'no_plan'; + +repeat_each(1); +log_level('info'); +no_root_location(); +no_shuffle(); +worker_connections(256); + +run_tests(); + +__DATA__ + +=== TEST 1: set route(two healthy upstream nodes) +--- 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": "/server_port", + "upstream": { + "type": "roundrobin", + "nodes": { + "127.0.0.1:1980": 1, + "127.0.0.1:1981": 1 + }, + "checks": { + "active": { + "http_path": "/status", + "host": "foo.com", + "healthy": { + "interval": 1, + "successes": 1 + }, + "unhealthy": { + "interval": 1, + "http_failures": 2 + } + } + } + } + }]] + ) + + if code >= 300 then + ngx.status = code + end + ngx.say(body) + } + } +--- request +GET /t +--- response_body +passed +--- grep_error_log eval +qr/^.*?\[error\](?!.*process exiting).*/ +--- grep_error_log_out + + + +=== TEST 2: In case of concurrency only one request can create a checker +--- config + location /t { + content_by_lua_block { + local healthcheck = require("resty.healthcheck") + local test = healthcheck.new + healthcheck.new = function(...) + ngx.sleep(1) + return test(...) + end + + local http = require "resty.http" + local uri = "http://127.0.0.1:" .. ngx.var.server_port + .. "/server_port" + + local send_request = function() + local httpc = http.new() + local res, err = httpc:request_uri(uri, {method = "GET", keepalive = false}) + if not res then + ngx.log(ngx.ERR, err) + return + end + end + + local t = {} + + for i = 1, 10 do + local th = assert(ngx.thread.spawn(send_request)) + table.insert(t, th) + end + + for i, th in ipairs(t) do + ngx.thread.wait(th) + end + + ngx.exit(200) + } + } +--- request +GET /t +--- grep_error_log eval +qr/create new checker/ +--- grep_error_log_out +create new checker diff --git a/t/plugin/cors2.t b/t/plugin/cors2.t index 67f6d6baa2fb..1bc223bd3e8b 100644 --- a/t/plugin/cors2.t +++ b/t/plugin/cors2.t @@ -89,3 +89,88 @@ __DATA__ } --- response_body done + + + +=== TEST 2: set route ( regex specified and allow_origins is default value ) +--- 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, + [[{ + "plugins": { + "cors": { + "allow_origins": "*", + "allow_methods": "GET,POST", + "allow_headers": "request-h", + "expose_headers": "expose-h", + "max_age": 10, + "allow_origins_by_regex":[".*\\.domain.com"] + } + }, + "upstream": { + "nodes": { + "127.0.0.1:1980": 1 + }, + "type": "roundrobin" + }, + "uri": "/hello" + }]] + ) + if code >= 300 then + ngx.status = code + end + ngx.say(body) + } + } +--- request +GET /t +--- response_body +passed + + + +=== TEST 3: regex specified not match +--- request +GET /hello HTTP/1.1 +--- more_headers +Origin: http://sub.test.com +resp-vary: Via +--- response_headers +Access-Control-Allow-Origin: +Access-Control-Allow-Methods: +Access-Control-Allow-Headers: +Access-Control-Expose-Headers: +Access-Control-Max-Age: +Access-Control-Allow-Credentials: + + + +=== TEST 4: regex no origin specified +--- request +GET /hello HTTP/1.1 +--- response_headers +Access-Control-Allow-Origin: +Access-Control-Allow-Methods: +Access-Control-Allow-Headers: +Access-Control-Expose-Headers: +Access-Control-Max-Age: +Access-Control-Allow-Credentials: + + + +=== TEST 5: regex specified match +--- request +GET /hello HTTP/1.1 +--- more_headers +Origin: http://sub.domain.com +resp-vary: Via +--- response_headers +Access-Control-Allow-Origin: http://sub.domain.com +Vary: Via +Access-Control-Allow-Methods: GET,POST +Access-Control-Allow-Headers: request-h +Access-Control-Expose-Headers: expose-h +Access-Control-Max-Age: 10 diff --git a/t/plugin/proxy-rewrite3.t b/t/plugin/proxy-rewrite3.t index eaea849cd432..45bcd6f5c918 100644 --- a/t/plugin/proxy-rewrite3.t +++ b/t/plugin/proxy-rewrite3.t @@ -622,3 +622,152 @@ GET /test/plugin/proxy/rewrite HTTP/1.1 } --- response_body /plugin_proxy_rewrite?a=c + + + +=== TEST 27: use variables in headers when captured by regex_uri +--- 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": "/test/*", + "plugins": { + "proxy-rewrite": { + "regex_uri": ["^/test/(.*)/(.*)/(.*)", "/echo"], + "headers": { + "add": { + "X-Request-ID": "$1/$2/$3" + } + } + } + }, + "upstream": { + "nodes": { + "127.0.0.1:1980": 1 + }, + "type": "roundrobin" + } + }]] + ) + + if code >= 300 then + ngx.status = code + end + ngx.say(body) + } + } +--- request +GET /t +--- response_body +passed + + + +=== TEST 28: hit +--- request +GET /test/plugin/proxy/rewrite HTTP/1.1 +--- response_headers +X-Request-ID: plugin/proxy/rewrite + + + +=== TEST 29: use variables in header when not matched regex_uri +--- 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": "/echo*", + "plugins": { + "proxy-rewrite": { + "regex_uri": ["^/test/(.*)/(.*)/(.*)", "/echo"], + "headers": { + "add": { + "X-Request-ID": "$1/$2/$3" + } + } + } + }, + "upstream": { + "nodes": { + "127.0.0.1:1980": 1 + }, + "type": "roundrobin" + } + }]] + ) + + if code >= 300 then + ngx.status = code + end + ngx.say(body) + } + } +--- request +GET /t +--- response_body +passed + + + +=== TEST 30: hit +--- request +GET /echo HTTP/1.1 +--- more_headers +X-Foo: Foo +--- response_headers +X-Foo: Foo + + + +=== TEST 31: use variables in headers when captured by regex_uri +--- 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": "/test/*", + "plugins": { + "proxy-rewrite": { + "regex_uri": ["^/test/(not_matched)?.*", "/echo"], + "headers": { + "add": { + "X-Request-ID": "test1/$1/$2/test2" + } + } + } + }, + "upstream": { + "nodes": { + "127.0.0.1:1980": 1 + }, + "type": "roundrobin" + } + }]] + ) + + if code >= 300 then + ngx.status = code + end + ngx.say(body) + } + } +--- request +GET /t +--- response_body +passed + + + +=== TEST 32: hit +--- request +GET /test/plugin/proxy/rewrite HTTP/1.1 +--- response_headers +X-Request-ID: test1///test2