Nginx 提供了多种方式在 HTTP 内容输出前进行拦截和修改,以下是主要的解决方案及其详细说明:
1. 使用 Lua 模块(推荐)Lua 模块提供了强大的动态处理能力,适合复杂的场景。
配置示例:http { lua_need_request_body on; server { location / { # 处理响应体 body_filter_by_lua_block { local chunk, eof = ngx.arg[1], ngx.arg[2] -- 修改响应内容 if chunk then chunk = string.gsub(chunk, "oldtext", "newtext") ngx.arg[1] = chunk end } # 或者使用外部 Lua 文件 body_filter_by_lua_file /path/to/filter.lua; } } }关键点:body_filter_by_lua_block:用于拦截和修改响应体。string.gsub:用于字符串替换。body_filter_by_lua_file:将逻辑放在外部 Lua 文件中,便于维护。2. 使用 Sub_Filter 模块
Sub_Filter 是 Nginx 内置模块,适合简单的字符串替换。
配置示例:location / { sub_filter '<old>' '<new>'; sub_filter_once off; sub_filter_types text/html text/css text/javascript; }关键点:sub_filter:用于替换字符串。sub_filter_once:控制是否只替换一次。sub_filter_types:指定需要处理的 MIME 类型。3. 使用 OpenResty 框架
OpenResty 是基于 Nginx 和 Lua 的完整开发框架,适合复杂的业务逻辑。
配置示例:location / { content_by_lua_block { -- 获取原始响应 local res = ngx.location.capture("/backend") -- 修改响应内容 local modified_body = string.gsub(res.body, "pattern", "replacement") -- 输出修改后的内容 ngx.print(modified_body) } }关键点:ngx.location.capture:获取后端响应。string.gsub:修改响应内容。ngx.print:输出修改后的内容。4. 使用 Headers More 模块
Headers More 模块用于修改响应头,适合简单的头部修改。
配置示例:location / { more_set_headers "Server: Custom Server"; more_set_headers "X-Custom-Header: Value"; }关键点:more_set_headers:用于设置或修改响应头。5. Lua 过滤器完整示例
以下是一个完整的 Lua 过滤器示例,支持字符串替换和 JSON 处理。
Lua 文件示例:-- filter.lua local _M = {} -- 初始化缓冲区 local buffer = "" function _M.filter(chunk, eof) if chunk then buffer = buffer .. chunk chunk = "" end if eof then -- 在这里处理完整的响应体 local modified = buffer:gsub("oldcontent", "newcontent") -- JSON 处理示例 if ngx.header.content_type and ngx.header.content_type:find("application/json") then local json = require("cjson") local data = json.decode(buffer) -- 修改 JSON 数据 data.modified = true modified = json.encode(data) end -- 返回修改后的内容 return modified else return "" end end return _M关键点:buffer:用于缓存响应体。string.gsub:字符串替换。cjson:处理 JSON 数据。6. 配置文件中使用变量和条件
Nginx 支持使用变量和条件来动态修改内容。
配置示例:http { # 定义变量 map $http_user_agent $is_mobile { default 0; "~*mobile" 1; } server { location / { set $modified_content ""; # 根据条件修改内容 body_filter_by_lua_block { local chunk = ngx.arg[1] if chunk and ngx.var.is_mobile == "1" then chunk = string.gsub(chunk, "desktop", "mobile") end ngx.arg[1] = chunk } } } }关键点:map:定义变量。body_filter_by_lua_block:根据变量值动态修改内容。注意事项:1. 性能考虑内容修改会影响性能,建议只对必要的响应进行处理。考虑使用缓存机制。2. 内存使用大文件处理需要注意内存使用,考虑分块处理大响应。3. 安装依赖
# 安装 LuaJIT apt-get install luajit # 或 yum install luajit # 安装 OpenResty wget https://openresty.org/download/openresty-VERSION.tar.gz tar xzvf openresty-VERSION.tar.gz cd openresty-VERSION/ ./configure make make install4. 调试技巧
# 在 Lua 代码中添加调试日志 ngx.log(ngx.ERR, "Debug: " .. tostring(variable)) # 配置 Nginx 错误日志级别 error_log /path/to/error.log debug;总结:Lua 模块:最灵活,功能最强大,适合复杂场景。Sub_Filter:最简单,但功能有限,适合简单的字符串替换。OpenResty:提供完整的开发框架,适合复杂的业务逻辑。Headers More:适合简单的头部修改。
选择哪种方案取决于:
修改需求的复杂度。性能要求。团队的技术栈。维护成本考虑。网友回复