test body chunks:

This commit is contained in:
wiaamm
2025-12-11 12:58:19 +02:00
parent 89d2a24d11
commit d9412680b6
2 changed files with 85 additions and 25 deletions

View File

@@ -51,7 +51,6 @@ function NanoHandler.access(conf)
local verdict, response = nano.send_data(session_id, session_data, meta_data, req_headers, contains_body, nano.HttpChunkType.HTTP_REQUEST_FILTER) local verdict, response = nano.send_data(session_id, session_data, meta_data, req_headers, contains_body, nano.HttpChunkType.HTTP_REQUEST_FILTER)
if verdict ~= nano.AttachmentVerdict.INSPECT then if verdict ~= nano.AttachmentVerdict.INSPECT then
kong.log.err("Failed to send request headers to C module - failing open")
ctx.cleanup_needed = true ctx.cleanup_needed = true
if verdict == nano.AttachmentVerdict.DROP then if verdict == nano.AttachmentVerdict.DROP then
return nano.handle_custom_response(session_data, response) return nano.handle_custom_response(session_data, response)
@@ -62,7 +61,7 @@ function NanoHandler.access(conf)
if contains_body == 1 then if contains_body == 1 then
local body = kong.request.get_raw_body() local body = kong.request.get_raw_body()
if body and #body > 0 then if body and #body > 0 then
kong.log.debug("Request body found in memory, size: ", #body) kong.log.err("Request body found in memory, size: ", #body)
verdict, response = nano.send_body(session_id, session_data, body, nano.HttpChunkType.HTTP_REQUEST_BODY) verdict, response = nano.send_body(session_id, session_data, body, nano.HttpChunkType.HTTP_REQUEST_BODY)
if verdict ~= nano.AttachmentVerdict.INSPECT then if verdict ~= nano.AttachmentVerdict.INSPECT then
ctx.cleanup_needed = true ctx.cleanup_needed = true
@@ -72,7 +71,7 @@ function NanoHandler.access(conf)
return return
end end
else else
kong.log.debug("Request body not in memory, attempting to read from buffer/file") kong.log.err("Request body not in memory, attempting to read from buffer/file")
local body_data = ngx.var.request_body local body_data = ngx.var.request_body
if body_data and #body_data > 0 then if body_data and #body_data > 0 then
kong.log.debug("Found request body in nginx var, size: ", #body_data) kong.log.debug("Found request body in nginx var, size: ", #body_data)
@@ -85,17 +84,21 @@ function NanoHandler.access(conf)
return return
end end
else else
kong.log.err("reading request body from file as last resort")
local body_file = ngx.var.request_body_file local body_file = ngx.var.request_body_file
if body_file then if body_file then
kong.log.debug("Reading request body from file: ", body_file) kong.log.err("Reading request body from file: ", body_file)
local file = io.open(body_file, "rb") local file = io.open(body_file, "rb")
if file then if file then
local chunk_size = 8192 local chunk_size = 8192
local chunk_count = 0 local chunk_count = 0
while true do while true do
kong.log.err("Reading next chunk from request body file")
local chunk = file:read(chunk_size) local chunk = file:read(chunk_size)
if not chunk or #chunk == 0 then if not chunk or #chunk == 0 then
kong .log.err("End of request body file reached")
break break
end end
@@ -113,10 +116,10 @@ function NanoHandler.access(conf)
end end
end end
file:close() file:close()
kong.log.debug("Sent ", chunk_count, " chunks from request body file") kong.log.err("Sent ", chunk_count, " chunks from request body file")
end end
else else
kong.log.debug("Request body expected but no body data or file available") kong.log.err("Request body expected but no body data or file available")
end end
end end
end end
@@ -172,7 +175,9 @@ function NanoHandler.header_filter(conf)
if verdict ~= nano.AttachmentVerdict.INSPECT then if verdict ~= nano.AttachmentVerdict.INSPECT then
ctx.cleanup_needed = true ctx.cleanup_needed = true
if verdict == nano.AttachmentVerdict.DROP then if verdict == nano.AttachmentVerdict.DROP then
return nano.handle_custom_response(session_data, response) kong.log.warn("DROP verdict in header_filter - will replace response in body_filter")
ctx.blocked = true
ctx.block_response = response
end end
return return
end end
@@ -184,7 +189,40 @@ function NanoHandler.body_filter(conf)
local ctx = kong.ctx.plugin local ctx = kong.ctx.plugin
local chunk = ngx.arg[1] local chunk = ngx.arg[1]
local eof = ngx.arg[2] local eof = ngx.arg[2]
if nano.is_session_finalized(ctx.session_data) then
local session_id = ctx.session_id
local session_data = ctx.session_data
if ctx.blocked then
if ctx.block_response then
local code, body, headers = nano.get_custom_response_data(session_data, ctx.block_response)
kong.log.info("Replacing response with custom response, code: ", code)
ngx.status = code
-- Set custom headers
for header_name, header_value in pairs(headers) do
ngx.header[header_name] = header_value
end
if body and #body > 0 then
ngx.header["Content-Length"] = #body
ngx.arg[1] = body
else
ngx.header["Content-Length"] = 0
ngx.arg[1] = ""
end
else
kong.log.err("Missing session_data or block_response, sending empty response")
ngx.status = 403
ngx.arg[1] = ""
end
ngx.arg[2] = true
ctx.cleanup_needed = true
return
end
if nano.is_session_finalized(session_data) then
kong.log.info("Session has already been inspected, no need for further inspection") kong.log.info("Session has already been inspected, no need for further inspection")
return return
end end
@@ -194,13 +232,6 @@ function NanoHandler.body_filter(conf)
return return
end end
local session_id = ctx.session_id
local session_data = ctx.session_data
if not session_id or not session_data then
kong.log.debug("No session data found in body_filter")
return
end
if not ctx.body_filter_start_time then if not ctx.body_filter_start_time then
ctx.body_filter_start_time = ngx.now() ctx.body_filter_start_time = ngx.now()
end end
@@ -227,9 +258,20 @@ function NanoHandler.body_filter(conf)
kong.log.debug("Final verdict for response body chunk: ", verdict) kong.log.debug("Final verdict for response body chunk: ", verdict)
ctx.cleanup_needed = true ctx.cleanup_needed = true
if verdict == nano.AttachmentVerdict.DROP then if verdict == nano.AttachmentVerdict.DROP then
ngx.arg[1] = "" kong.log.warn("DROP verdict in body_filter - replacing response immediately")
local code, body, headers = nano.get_custom_response_data(session_data, response)
ngx.status = code
for header_name, header_value in pairs(headers) do
ngx.header[header_name] = header_value
end
if body and #body > 0 then
ngx.header["Content-Length"] = #body
ngx.arg[1] = body
else
ngx.header["Content-Length"] = 0
ngx.arg[1] = ""
end
ngx.arg[2] = true ngx.arg[2] = true
return nano.handle_custom_response(session_data, response)
end end
return return
end end
@@ -243,9 +285,20 @@ function NanoHandler.body_filter(conf)
kong.log.debug("Final verdict after end_inspection: ", verdict) kong.log.debug("Final verdict after end_inspection: ", verdict)
ctx.cleanup_needed = true ctx.cleanup_needed = true
if verdict == nano.AttachmentVerdict.DROP then if verdict == nano.AttachmentVerdict.DROP then
ngx.arg[1] = "" kong.log.warn("DROP verdict at EOF - replacing response immediately")
local code, body, headers = nano.get_custom_response_data(session_data, response)
ngx.status = code
for header_name, header_value in pairs(headers) do
ngx.header[header_name] = header_value
end
if body and #body > 0 then
ngx.header["Content-Length"] = #body
ngx.arg[1] = body
else
ngx.header["Content-Length"] = 0
ngx.arg[1] = ""
end
ngx.arg[2] = true ngx.arg[2] = true
return nano.handle_custom_response(session_data, response)
end end
return return
end end

View File

@@ -81,13 +81,14 @@ function nano.generate_session_id()
return tonumber(string.format("%d%05d", worker_id, nano.session_counter)) return tonumber(string.format("%d%05d", worker_id, nano.session_counter))
end end
function nano.handle_custom_response(session_data, response) -- Returns: status_code, body, headers
function nano.get_custom_response_data(session_data, response)
local worker_id = ngx.worker.id() local worker_id = ngx.worker.id()
local attachment = nano.attachments[worker_id] local attachment = nano.attachments[worker_id]
if not attachment then if not attachment then
kong.log.warn("Cannot handle custom response: Attachment not available for worker ", worker_id, " - failing open") kong.log.warn("Cannot handle custom response: Attachment not available for worker ", worker_id, " - failing open")
return kong.response.exit(200, "Request allowed due to attachment unavailability") return 200, "Request allowed due to attachment unavailability", {}
end end
local response_type = nano_attachment.get_web_response_type(attachment, session_data, response) local response_type = nano_attachment.get_web_response_type(attachment, session_data, response)
@@ -99,18 +100,19 @@ function nano.handle_custom_response(session_data, response)
code = 403 code = 403
end end
kong.log.debug("Response code only: ", code) kong.log.debug("Response code only: ", code)
return kong.response.exit(code, "") return code, "", {}
end end
if response_type == nano.WebResponseType.REDIRECT_WEB_RESPONSE then if response_type == nano.WebResponseType.REDIRECT_WEB_RESPONSE then
local location = nano_attachment.get_redirect_page(attachment, session_data, response) local location = nano_attachment.get_redirect_page(attachment, session_data, response)
return kong.response.exit(307, "", { ["Location"] = location }) local code = nano_attachment.get_response_code(response) or 307
return code, "", { ["Location"] = location }
end end
local block_page = nano_attachment.get_block_page(attachment, session_data, response) local block_page = nano_attachment.get_block_page(attachment, session_data, response)
if not block_page then if not block_page then
kong.log.err("Failed to retrieve custom block page for session ", session_data) kong.log.err("Failed to retrieve custom block page for session ", session_data)
return kong.response.exit(500, { message = "Internal Server Error" }) return 403, "", {}
end end
local code = nano_attachment.get_response_code(response) local code = nano_attachment.get_response_code(response)
if not code or code < 100 or code > 599 then if not code or code < 100 or code > 599 then
@@ -118,8 +120,13 @@ function nano.handle_custom_response(session_data, response)
code = 403 code = 403
end end
kong.log.debug("Block page response with code: ", code) kong.log.debug("Block page response with code: ", code)
return kong.response.exit(code, block_page, { ["Content-Type"] = "text/html" }) return code, block_page, { ["Content-Type"] = "text/html" }
end
-- Wrapper for backward compatibility - calls kong.response.exit() in access phase
function nano.handle_custom_response(session_data, response)
local code, body, headers = nano.get_custom_response_data(session_data, response)
return kong.response.exit(code, body, headers)
end end