-
Notifications
You must be signed in to change notification settings - Fork 134
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
I improved healthcheck library so that it supports contains / exact matc... #3
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -19,6 +19,15 @@ local fmod = math.fmod | |
local spawn = ngx.thread.spawn | ||
local wait = ngx.thread.wait | ||
|
||
local http_descriptor = {} | ||
http_descriptor["1.0"] = { | ||
delimiter_body = "\r\n" | ||
} | ||
|
||
http_descriptor["1.1"] = { | ||
delimiter_body = "\r\n\r\n" | ||
} | ||
|
||
local _M = { | ||
_VERSION = '0.03' | ||
} | ||
|
@@ -199,6 +208,25 @@ local function peer_ok(ctx, is_backup, id, peer) | |
end | ||
end | ||
|
||
--- This method is used to detect if a http message body matches the expected body specified | ||
-- in an upstream healtcheck. If the expected_body is a contains expression (%) then it tries | ||
-- to read from socket till it gets the string from %%. Otherwise it does an exact read of bytes | ||
-- and compare the result with the expected body. | ||
local function is_expectedbody(socket, expected_body, http_version) | ||
local readuntilnew = socket:receiveuntil(http_descriptor[http_version]["delimiter_body"]) | ||
local headers = readuntilnew() | ||
|
||
if not string.find(expected_body, "%%") then | ||
local body = socket:receive(string.len(expected_body)) | ||
|
||
return body == expected_body | ||
end | ||
|
||
expected_body = string.gsub(expected_body, "%%", "") | ||
|
||
return socket:receiveuntil(expected_body)() | ||
end | ||
|
||
local function check_peer(ctx, id, peer, is_backup) | ||
local u = ctx.upstream | ||
local ok, err | ||
|
@@ -260,7 +288,17 @@ local function check_peer(ctx, id, peer, is_backup) | |
end | ||
peer_fail(ctx, is_backup, id, peer) | ||
else | ||
peer_ok(ctx, is_backup, id, peer) | ||
if ctx.expected_body then | ||
if not is_expectedbody(sock, ctx.expected_body, ctx.http_version) then | ||
errlog(string.format("Received body from %s does not match %s", | ||
name, ctx.expected_body)) | ||
peer_fail(ctx, is_backup, id, peer) | ||
else | ||
peer_ok(ctx, is_backup, id, peer) | ||
end | ||
else | ||
peer_ok(ctx, is_backup, id, peer) | ||
end | ||
end | ||
end | ||
else | ||
|
@@ -600,8 +638,14 @@ function _M.spawn_checker(opts) | |
statuses = statuses, | ||
version = 0, | ||
concurrency = concur, | ||
http_version = opts.http_version or "1.1", | ||
expected_body = opts.expected_body | ||
} | ||
|
||
if ctx.http_version ~= "1.1" or ctx.http_version ~= "1.0" then | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. shouldn't this be an AND operator? You probably want; if ctx.http_version ~= "1.0" then
ctx.http_version = "1.1"
end There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I just commented on the line, but actually the checks should be done further up, before the and then it should be something like; local http_allowed = { ["1.0"] = true, ["1.1"] = true }
local http_version = opts.http_version or "1.1"
if not http_allowed[http_version] then
return nil, "invalid http version: "..tostring(http_version)
end
|
||
ctx.http_version = "1.1" | ||
end | ||
|
||
local ok, err = new_timer(0, check, ctx) | ||
if not ok then | ||
return nil, "failed to create timer: " .. err | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this is the right thing to do. Since it introduces unnecessary delay (till timeout) if the body does not contain the expected pattern, which is rather wasteful. Also, this approach will fail when the chunked encoding is used and a chunk boundary happens to split the part matching the pattern.