Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hotfix/add healthcheck in response body #45

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 42 additions & 0 deletions .idea/workspace.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

41 changes: 41 additions & 0 deletions lib/resty/healthcheck.lua
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ local ssl = require("ngx.ssl")
local resty_timer = require "resty.timer"
local bit = require("bit")
local re_find = ngx.re.find
local ngx_re_match = ngx.re.match
local ngx_now = ngx.now
local ngx_worker_id = ngx.worker.id
local ngx_worker_pid = ngx.worker.pid
Expand Down Expand Up @@ -1149,6 +1150,45 @@ function checker:run_single_check(ip, port, hostname, hostheader)
self:log(ERR, "bad status line from '", hostname, " (", ip, ":", port, ")': ", status_line)
-- note: 'status' will be reported as 'nil'
end
if self.checks.active.body_match_str ~= "" then
local content_length
repeat
local line, err = sock:receive()
if not line then
return nil, err
end

local m, err = ngx_re_match(line, "([^:\\s]+):\\s*(.*)", "jo")
if err then ngx_log(ERR, err) end

if not m then
break
end
if m[1] == "content-length" then
content_length = m[2]
end
until re_find(line, "^\\s*$", "jo")
if content_length then
content_length = tonumber(content_length)
if content_length <= 4096 then
local str, err, partial = sock:receive(content_length)
if str == self.checks.active.body_match_str then
sock:close()
return self:report_http_status(ip, port, hostname, status, "active")
else
sock:close()
return self:report_tcp_failure(ip, port, hostname, "receive", "active")
end
else
sock:close()
return self:report_tcp_failure(ip, port, hostname, "receive", "active")
end
else
sock:close()
return self:report_tcp_failure(ip, port, hostname, "receive", "active")
end
end


sock:close()

Expand Down Expand Up @@ -1507,6 +1547,7 @@ local defaults = {
http_failures = 5,
},
req_headers = {""},
body_match_str = "",
},
passive = {
type = "http",
Expand Down
217 changes: 217 additions & 0 deletions t/with_resty-events/19-body_match.t
Original file line number Diff line number Diff line change
@@ -0,0 +1,217 @@
use Test::Nginx::Socket::Lua;
use Cwd qw(cwd);

workers(1);

plan tests => repeat_each() * 9;

my $pwd = cwd();
$ENV{TEST_NGINX_SERVROOT} = server_root();

our $HttpConfig = qq{
lua_package_path "$pwd/lib/?.lua;;";
lua_shared_dict test_shm 8m;

init_worker_by_lua_block {
local we = require "resty.events.compat"
assert(we.configure({
unique_timeout = 5,
broker_id = 0,
listening = "unix:$ENV{TEST_NGINX_SERVROOT}/worker_events.sock"
}))
assert(we.configured())
}

server {
server_name kong_worker_events;
listen unix:$ENV{TEST_NGINX_SERVROOT}/worker_events.sock;
access_log off;
location / {
content_by_lua_block {
require("resty.events.compat").run()
}
}
}
};

run_tests();

__DATA__



=== TEST 1: test body_match_str success
--- http_config eval
qq{
$::HttpConfig

# ignore lua tcp socket read timed out
lua_socket_log_errors off;

server {
listen 2114;
location = /status {
access_by_lua_block {
ngx.sleep(0.2)
ngx.header['content-length'] = '4'
ngx.say("pass")
ngx.satus = 200
return
}
}
}
}
--- config
location = /t {
content_by_lua_block {
local healthcheck = require("resty.healthcheck")
local checker = healthcheck.new({
test = true,
name = "testing",
shm_name = "test_shm",
events_module = "resty.events",
type = "http",
checks = {
active = {
http_path = "/status",
healthy = {
interval = 0.1,
},
unhealthy = {
interval = 0.1,
},
body_match_str = 'pass'
},
}
})
ngx.sleep(1) -- active healthchecks might take up to 1s to start
local ok, err = checker:add_target("127.0.0.1", 2114, nil, true)
ngx.sleep(1) -- wait for the check interval
ngx.say(checker:get_target_status("127.0.0.1", 2114))
}
}
--- request
GET /t
--- response_body
true
--- no_error_log
[error]



=== TEST 2: test body_match_str failed
--- http_config eval
qq{
$::HttpConfig

# ignore lua tcp socket read timed out
lua_socket_log_errors off;

server {
listen 2114;
location = /status {
access_by_lua_block {
ngx.sleep(0.2)
ngx.header['content-length'] = '4'
ngx.say("pass")
ngx.satus = 200
return
}
}
}
}
--- config
location = /t {
content_by_lua_block {
local healthcheck = require("resty.healthcheck")
local checker = healthcheck.new({
test = true,
name = "testing",
shm_name = "test_shm",
events_module = "resty.events",
type = "http",
checks = {
active = {
http_path = "/status",
healthy = {
interval = 0.1,
},
unhealthy = {
interval = 0.1,
},
body_match_str = 'fail'
},
}
})
ngx.sleep(1) -- active healthchecks might take up to 1s to start
local ok, err = checker:add_target("127.0.0.1", 2114, nil, true)
ngx.sleep(1) -- wait for the check interval
ngx.say(checker:get_target_status("127.0.0.1", 2114))
}
}
--- request
GET /t
--- response_body
false
--- no_error_log
[error]



=== TEST 3: test body_match_str empty
--- http_config eval
qq{
$::HttpConfig

# ignore lua tcp socket read timed out
lua_socket_log_errors off;

server {
listen 2114;
location = /status {
access_by_lua_block {
ngx.sleep(0.2)
ngx.header['content-length'] = '4'
ngx.say("pass")
ngx.satus = 200
return
}
}
}
}
--- config
location = /t {
content_by_lua_block {
local healthcheck = require("resty.healthcheck")
local checker = healthcheck.new({
test = true,
name = "testing",
shm_name = "test_shm",
events_module = "resty.events",
type = "http",
checks = {
active = {
http_path = "/status",
healthy = {
interval = 0.1,
},
unhealthy = {
interval = 0.1,
},
body_match_str = ''
},
}
})
ngx.sleep(1) -- active healthchecks might take up to 1s to start
local ok, err = checker:add_target("127.0.0.1", 2114, nil, true)
ngx.sleep(1) -- wait for the check interval
ngx.say(checker:get_target_status("127.0.0.1", 2114))
}
}
--- request
GET /t
--- response_body
true
--- no_error_log
[error]