ikibooru/pegasus/plugins/compress.lua

146 lines
3.9 KiB
Lua
Raw Normal View History

2024-06-01 17:40:11 +03:00
local zlib = require "zlib"
local function zlib_name(lib)
if lib._VERSION and string.find(lib._VERSION, 'lua-zlib', nil, true) then
return 'lua-zlib'
end
if lib._VERSION and string.find(lib._VERSION, 'lzlib', nil, true) then
return 'lzlib'
end
end
local z_lib_name = assert(zlib_name(zlib), 'Unsupported zlib Lua binding')
local ZlibStream = {} do
ZlibStream.__index = ZlibStream
ZlibStream.NO_COMPRESSION = zlib.NO_COMPRESSION or 0
ZlibStream.BEST_SPEED = zlib.BEST_SPEED or 1
ZlibStream.BEST_COMPRESSION = zlib.BEST_COMPRESSION or 9
ZlibStream.DEFAULT_COMPRESSION = zlib.DEFAULT_COMPRESSION or -1
ZlibStream.STORE = 0
ZlibStream.DEFLATE = 8
if z_lib_name == 'lzlib' then
function ZlibStream:new(writer, level, method, windowBits)
level = level or ZlibStream.DEFAULT_COMPRESSION
method = method or ZlibStream.DEFLATE
local o = setmetatable({
zd = assert(zlib.deflate(writer, level, method, windowBits));
}, self)
return o
end
function ZlibStream:write(chunk)
assert(self.zd:write(chunk))
end
function ZlibStream:close()
self.zd:close()
end
elseif z_lib_name == 'lua-zlib' then
function ZlibStream:new(writer, level, method, windowBits)
level = level or ZlibStream.DEFAULT_COMPRESSION
method = method or ZlibStream.DEFLATE
assert(method == ZlibStream.DEFLATE, 'lua-zlib support only deflated method')
local o = setmetatable({
zd = assert(zlib.deflate(level, windowBits));
writer = writer;
}, self)
return o
end
function ZlibStream:write(chunk)
chunk = assert(self.zd(chunk))
self.writer(chunk)
end
function ZlibStream:close()
local chunk = self.zd('', 'finish')
if chunk and #chunk > 0 then self.writer(chunk) end
end
end
end
local Compress = {} do
Compress.__index = Compress
Compress.NO_COMPRESSION = ZlibStream.NO_COMPRESSION
Compress.BEST_SPEED = ZlibStream.BEST_SPEED
Compress.BEST_COMPRESSION = ZlibStream.BEST_COMPRESSION
Compress.DEFAULT_COMPRESSION = ZlibStream.DEFAULT_COMPRESSION
function Compress:new(options)
local compress = {}
compress.options = options or {}
return setmetatable(compress, self)
end
function Compress:processBodyData(data, stayOpen, request, response)
local accept_encoding
if response.headersSended then
accept_encoding = response.headers['Content-Encoding'] or ''
else
local headers = request:headers()
accept_encoding = headers and headers['Accept-Encoding'] or ''
end
local accept_gzip = not not accept_encoding:find('gzip', nil, true)
if accept_gzip and self.options.level ~= ZlibStream.NO_COMPRESSION then
local stream = response.compress_stream
local buffer = response.compress_buffer
if not stream then
local writer = function (zdata) buffer[#buffer + 1] = zdata end
stream, buffer = ZlibStream:new(writer, self.options.level, nil, 31), {}
end
if stayOpen then
if data == nil then
stream:close()
response.compress_stream = nil
response.compress_buffer = nil
else
stream:write(data)
response.compress_stream = stream
response.compress_buffer = buffer
end
local compressed = table.concat(buffer)
for i = 1, #buffer do buffer[i] = nil end
if not response.headersSended then
response:addHeader('Content-Encoding', 'gzip')
end
return compressed
end
stream:write(data)
stream:close()
local compressed = table.concat(buffer)
if #compressed < #data then
if not response.headersSended then
response:addHeader('Content-Encoding', 'gzip')
end
return compressed
end
end
return data
end
end
return Compress