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:适合简单的头部修改。
选择哪种方案取决于:
修改需求的复杂度。性能要求。团队的技术栈。维护成本考虑。网友回复


