diff --git a/README.md b/README.md index e150a85e..2582917d 100644 --- a/README.md +++ b/README.md @@ -110,6 +110,8 @@ Versioning is strictly based on [Semantic Versioning](https://semver.org/) * fix: properly log line numbers by using tail calls [#29](https://github.com/Kong/lua-resty-healthcheck/pull/29) * fix: when not providing a hostname, use IP [#48](https://github.com/Kong/lua-resty-healthcheck/pull/48) * fix: makefile; make install +* feature: added a status version field [#54](https://github.com/Kong/lua-resty-healthcheck/pull/54) +* feature: add headers for probe request [#54](https://github.com/Kong/lua-resty-healthcheck/pull/54) ### 1.3.0 (17-Jun-2020) diff --git a/lib/resty/healthcheck.lua b/lib/resty/healthcheck.lua index 1685edc9..58eeeb8d 100644 --- a/lib/resty/healthcheck.lua +++ b/lib/resty/healthcheck.lua @@ -850,8 +850,15 @@ function checker:run_single_check(ip, port, hostname, hostheader) end + local req_headers = self.checks.active.headers + local headers = table.concat(req_headers, "\r\n") + if #headers > 0 then + headers = headers .. "\r\n" + end + local path = self.checks.active.http_path - local request = ("GET %s HTTP/1.0\r\nHost: %s\r\n\r\n"):format(path, hostheader or hostname) + local request = ("GET %s HTTP/1.0\r\n%sHost: %s\r\n\r\n"):format(path, headers, hostheader or hostname or ip) + self:log(DEBUG, "request head: ", request) local bytes bytes, err = sock:send(request) @@ -1076,11 +1083,17 @@ function checker:event_handler(event_name, ip, port, hostname) self:log(DEBUG, "event: target added '", hostname or "", "(", ip, ":", port, ")'") end do - local from = target_found.internal_health - local to = event_name - self:log(DEBUG, "event: target status '", hostname or "", "(", ip, ":", port, - ")' from '", from == "healthy" or from == "mostly_healthy", - "' to '", to == "healthy" or to == "mostly_healthy", "'") + local from_status = target_found.internal_health + local to_status = event_name + local from = from_status == "healthy" or from_status == "mostly_healthy" + local to = to_status == "healthy" or to_status == "mostly_healthy" + + if from ~= to then + self.status_ver = self.status_ver + 1 + end + + self:log(DEBUG, "event: target status '", hostname or "", "(", ip, ":", + port, ")' from '", from, "' to '", to, "', ver: ", self.status_ver) end target_found.internal_health = event_name @@ -1214,6 +1227,7 @@ local defaults = { name = NO_DEFAULT, shm_name = NO_DEFAULT, type = NO_DEFAULT, + status_ver = 0, checks = { active = { type = "http", @@ -1222,6 +1236,7 @@ local defaults = { http_path = "/", https_sni = NO_DEFAULT, https_verify_certificate = true, + headers = {""}, healthy = { interval = 0, -- 0 = disabled by default http_statuses = { 200, 302 }, @@ -1294,6 +1309,7 @@ end -- * `checks.active.http_path`: path to use in `GET` HTTP request to run on active checks -- * `checks.active.https_sni`: SNI server name incase of HTTPS -- * `checks.active.https_verify_certificate`: boolean indicating whether to verify the HTTPS certificate +-- * `checks.active.hheaders`: an array of headers (no hash-table! must be pre-formatted) -- * `checks.active.healthy.interval`: interval between checks for healthy targets (in seconds) -- * `checks.active.healthy.http_statuses`: which HTTP statuses to consider a success -- * `checks.active.healthy.successes`: number of successes to consider a target healthy diff --git a/t/19-status-ver.t b/t/19-status-ver.t new file mode 100644 index 00000000..c7d2166f --- /dev/null +++ b/t/19-status-ver.t @@ -0,0 +1,62 @@ +use Test::Nginx::Socket::Lua 'no_plan'; +use Cwd qw(cwd); + +workers(2); +master_on(); + +my $pwd = cwd(); + +our $HttpConfig = qq{ + lua_package_path "$pwd/lib/?.lua;;"; + lua_shared_dict test_shm 8m; + lua_shared_dict my_worker_events 8m; + + init_worker_by_lua_block { + local we = require "resty.worker.events" + assert(we.configure{ shm = "my_worker_events", interval = 0.1 }) + ngx.timer.at(0, function() + local healthcheck = require("resty.healthcheck") + local checker = healthcheck.new({ + name = "testing", + shm_name = "test_shm", + checks = { + active = { + healthy = { + interval = 0.1 + }, + unhealthy = { + interval = 0.1 + } + } + } + }) + local ok, err = checker:add_target("127.0.0.1", 11111) + if not ok then + error(err) + end + end) + } +}; + +run_tests(); + +__DATA__ + +=== TEST 1: add_target() adds an unhealthy target +--- http_config eval: $::HttpConfig +--- config + location = /t { + content_by_lua_block { + ngx.say(true) + ngx.sleep(0.3) -- wait twice the interval + } + } +--- request +GET /t +--- response_body +true +--- error_log +checking unhealthy targets: nothing to do +checking unhealthy targets: #1 +from 'true' to 'false', ver: 2 +from 'true' to 'false', ver: 1 diff --git a/t/20-req-headers.t b/t/20-req-headers.t new file mode 100644 index 00000000..304315db --- /dev/null +++ b/t/20-req-headers.t @@ -0,0 +1,114 @@ +use Test::Nginx::Socket::Lua 'no_plan'; +use Cwd qw(cwd); + +workers(1); + +my $pwd = cwd(); + +our $HttpConfig = qq{ + lua_package_path "$pwd/lib/?.lua;;"; + lua_shared_dict test_shm 8m; + lua_shared_dict my_worker_events 8m; +}; + +run_tests(); + +__DATA__ + +=== TEST 1: headers: {"User-Agent", "curl/7.29.0"} +--- http_config eval +qq{ + $::HttpConfig + + server { + listen 2112; + location = /status { + return 200; + } + } +} +--- config + location = /t { + content_by_lua_block { + local we = require "resty.worker.events" + assert(we.configure{ shm = "my_worker_events", interval = 0.1 }) + local healthcheck = require("resty.healthcheck") + local checker = healthcheck.new({ + name = "testing", + shm_name = "test_shm", + checks = { + active = { + http_path = "/status", + healthy = { + interval = 0.1 + }, + headers = {"User-Agent: curl/7.29.0"} + } + } + }) + ngx.sleep(0.2) -- wait twice the interval + local ok, err = checker:add_target("127.0.0.1", 2112, nil, true) + ngx.say(ok) + ngx.sleep(0.2) -- wait twice the interval + } + } +--- request +GET /t +--- response_body +true +--- error_log +checking healthy targets: nothing to do +checking healthy targets: #1 +GET /status HTTP/1.0 +User-Agent: curl/7.29.0 +Host: 127.0.0.1 + + + +=== TEST 2: headers: {"User-Agent", "curl"} +--- http_config eval +qq{ + $::HttpConfig + + server { + listen 2112; + location = /status { + return 200; + } + } +} +--- config + location = /t { + content_by_lua_block { + local we = require "resty.worker.events" + assert(we.configure{ shm = "my_worker_events", interval = 0.1 }) + local healthcheck = require("resty.healthcheck") + local checker = healthcheck.new({ + name = "testing", + shm_name = "test_shm", + checks = { + active = { + http_path = "/status", + healthy = { + interval = 0.1 + }, + headers = {"User-Agent: curl"} + } + } + }) + ngx.sleep(0.2) -- wait twice the interval + local ok, err = checker:add_target("127.0.0.1", 2112, nil, true) + ngx.say(ok) + ngx.sleep(0.2) -- wait twice the interval + } + } +--- request +GET /t +--- response_body +true +--- error_log +checking healthy targets: nothing to do +checking healthy targets: #1 +GET /status HTTP/1.0 +User-Agent: curl +Host: 127.0.0.1