-- webp_handler.lua local os = os local io = io -- ################### 配置区 ################### local CACHE_ROOT = varwwwmysitewebp_cache local DOCUMENT_ROOT = varwwwmysitepublic local CWEBP_PATH = usrbincwebp -- 使用 'which cwebp' 命令查找确切路径 local QUALITY = 80 -- WebP 图片质量 (0-100) -- ############################################# function is_image_request() local uri = ls.req.uri() local image_extensions = { jpg, jpeg, png, gif, JPG, JPEG, PNG, GIF } for _, ext in ipairs(image_extensions) do if string.find(uri, %. .. ext .. $) then return true, uri end end return false, uri end function browser_accepts_webp() local headers = ls.req.get_headers() local accept_header = headers['Accept'] or return string.find(accept_header, imagewebp) ~= nil end function get_webp_cache_path(original_uri) -- 将原始URI中的文件名后加上 .webp 后缀 local webp_uri = original_uri .. .webp -- 构建完整的缓存文件系统路径 local full_cache_path = CACHE_ROOT .. webp_uri -- 构建原始图片的完整文件系统路径 local full_original_path = DOCUMENT_ROOT .. original_uri return full_cache_path, full_original_path, webp_uri end function file_exists(path) local file = io.open(path, rb) if file then fileclose() return true end return false end function convert_to_webp(source_path, dest_path) -- 构建并执行转换命令 local command = string.format(%s -q %s '%s' -o '%s' 2&1, CWEBP_PATH, QUALITY, source_path, dest_path) local handle = io.popen(command) local result = handleread(a) local success, _, exit_code = handleclose() -- 注意:io.popen 在 Lua 中的返回值处理因环境而异 -- 更可靠的检查是看目标文件是否被创建 if file_exists(dest_path) then return true, Success else return false, Conversion failed .. (result or unknown error) end end function serve_file(file_path, content_type) -- 设置正确的 Content-Type 并发送文件 ls.header.set(Content-Type, content_type) ls.header.set(Cache-Control, public, max-age=31536000) -- 缓存一年 ls.sendfile(file_path) end -- 主函数 function handle_request() local is_image, requested_uri = is_image_request() -- 1. 如果不是图片请求,跳过处理 if not is_image then return 0 end -- 2. 检查浏览器是否支持 WebP if not browser_accepts_webp() then return 0 -- 让服务器继续处理原图 end -- 3. 获取缓存路径 local webp_cache_path, original_file_path, webp_uri = get_webp_cache_path(requested_uri) local cache_dir = webp_cache_pathmatch((.[])) os.execute(mkdir -p ' .. cache_dir .. ') -- 确保缓存目录存在 -- 4. 检查原图是否存在 if not file_exists(original_file_path) then return 0 end -- 5. 检查 WebP 缓存是否已存在 if file_exists(webp_cache_path) then -- 缓存存在,直接服务缓存文件 serve_file(webp_cache_path, imagewebp) return 1 -- 请求已处理,无需继续 end -- 6. 缓存不存在,进行转换 local conversion_success, message = convert_to_webp(original_file_path, webp_cache_path) if conversion_success then -- 转换成功,服务新生成的缓存文件 serve_file(webp_cache_path, imagewebp) return 1 else -- 转换失败,记录日志并回退到原图 ls.log(ls.LS_LOG_ERROR, WebP conversion failed for .. original_file_path .. .. message) return 0 end end -- 注册处理函数 rewrite = handle_request