Skip to content

Instantly share code, notes, and snippets.

@nicky-zs
Created July 17, 2016 02:57
Show Gist options
  • Save nicky-zs/b395ff5fbcad6ed734357dbc120f597e to your computer and use it in GitHub Desktop.
Save nicky-zs/b395ff5fbcad6ed734357dbc120f597e to your computer and use it in GitHub Desktop.
Supporting gzipped request body.
-- lua-zlib is required
local MAX_BODY_SIZE = 16777216
ngx.ctx.max_chunk_size = tonumber(ngx.var.max_chunk_size) or 262144 -- 256KB
ngx.ctx.max_body_size = tonumber(ngx.var.max_body_size) or MAX_BODY_SIZE -- 16MB
function bad_request_response(status, msg)
local message = string.format('{"status": %d, "msg": "%s"}', status, msg)
ngx.status = ngx.HTTP_BAD_REQUEST
ngx.header.content_type = "application/json"
ngx.say(message)
ngx.exit(ngx.HTTP_OK)
end
function inflate_body(data)
local stream = require("zlib").inflate()
local buffer = ""
local chunk = ""
for index = 0, data:len(), ngx.ctx.max_chunk_size do
chunk = string.sub(data, index, index + ngx.ctx.max_chunk_size - 1)
local status, output, eof, bytes_in, bytes_out = pcall(stream, chunk)
if not status then -- corrupted chunk
ngx.log(ngx.ERR, output)
bad_request_response(4003, "gzip格式已损坏")
end
if bytes_in == 0 and bytes_out == 0 then -- body is not gzip compressed
bad_request_response(4004, "非gzip压缩格式")
end
buffer = buffer .. output
if bytes_out > ngx.ctx.max_body_size then -- uncompressed body too large
bad_request_response(4005, "gzip解压结果太大")
end
end
return buffer
end
local headers = ngx.req.get_headers()
local content_length = headers["Content-Length"]
local content_encoding = headers["Content-Encoding"]
if content_length and tonumber(content_length) > MAX_BODY_SIZE then
bad_request_response(4005, "gzip解压结果太大")
end
if content_encoding and content_encoding:lower() == "gzip" then
ngx.req.read_body()
local data = ngx.req.get_body_data()
if data == nil then
local file_name = ngx.req.get_body_file()
if file_name ~= nil and file_name ~= '' then
local file = io.open(file_name, "r")
data = file:read("*a")
file:close()
end
end
if data ~= nil and data ~= '' then
if data:len() > MAX_BODY_SIZE then
bad_request_response(4005, "gzip解压结果太大")
end
local new_data = inflate_body(data)
ngx.req.clear_header("Content-Encoding")
ngx.req.clear_header("Content-Length")
ngx.req.set_body_data(new_data)
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment