OpenResty 怎么通过 Lua 脚本实现请求与响应内容的动态替换

大辰小哥_4878

大辰小哥_4878

2026-09-05

213人浏览

原创

openresty 通过 body_filter_by_lua 流式替换响应体文本最常用安全,header_filter_by_lua 修改响应头或注入内容,rewrite_by_lua* 预处理请求路径参数;需注意 chunk 截断、二进制内容保护及性能优化。

openresty 怎么通过 lua 脚本实现请求与响应内容的动态替换

OpenResty 可以通过 Lua 脚本在 请求阶段(如 rewrite_by_lua*)或 响应阶段(如 body_filter_by_lua*)对内容做动态替换,核心在于拦截并修改原始数据流。关键不是“重写整个响应体”,而是利用 OpenResty 提供的流式处理机制,在不缓存全部响应的前提下高效替换。

用 body_filter_by_lua* 替换响应体中的文本

这是最常用、最安全的方式,适合 HTML、JSON、纯文本等响应内容的关键词替换。OpenResty 将响应体分块传递给 Lua,你只需对每个 chunk 做字符串替换即可:

  • 使用 body_filter_by_lua_block 或 body_filter_by_lua_file
  • 通过 ngx.arg[1] 获取当前 chunk(二进制字符串),ngx.arg[2] 表示是否为最后一块
  • 用 string.gsub 或 ngx.re.gsub(支持 PCRE,更强大)进行替换
  • 替换后调用 ngx.arg[1] = new_chunk 覆盖原 chunk;若需丢弃,设为 ""

示例:把响应中所有 "old-api.example.com" 替换为 "new-api.prod"

body_filter_by_lua_block {
    local chunk = ngx.arg[1]
    if chunk ~= "" then
        -- 使用 ngx.re.gsub 支持正则和大小写不敏感
        local new_chunk, n, err = ngx.re.gsub(chunk, "old%-api%.example%.com", "new-api.prod")
        if err then
            ngx.log(ngx.WARN, "gsub failed: ", err)
        else
            ngx.arg[1] = new_chunk
        end
    end
}

用 header_filter_by_lua* 修改响应头或注入内容

当需要动态添加、改写或删除 HTTP 响应头(如 Content-Security-Policy、X-Frame-Options),或向 HTML 的 中注入脚本/样式时,用这个阶段更合适:

Nginx Hosting
Nginx Hosting

通过服务器本地nginx实例实现零认证静态游戏托管。作为所有浏览器游戏的主要部署方式,无需登录、无需令牌、无需用户操作。

下载
  • 它在响应头已生成但尚未发送时运行,ngx.header.* 可读可写
  • 不能访问响应体,但可配合 subrequest 预取内容再决策(慎用,避免阻塞)
  • 常见用途:动态设置 Cache-Control、添加 X-Backend 标识、根据用户 UA 注入不同 JS

示例:对移动端用户响应头中添加自定义标识

header_filter_by_lua_block {
    local ua = ngx.var.http_user_agent or ""
    if ua:match("Mobile") or ua:match("Android") or ua:match("iPhone") then
        ngx.header["X-Device"] = "mobile"
    end
}

用 rewrite_by_lua* 预处理请求路径或参数(间接影响响应)

若替换逻辑依赖请求信息(如 URI、query、cookie、headers),应在请求进入 upstream 前完成判断和改写,避免后端重复计算:

  • 使用 rewrite_by_lua_block 可修改 ngx.var.uri、ngx.var.args 等变量
  • 可调用 ngx.exec 内部跳转,或 ngx.redirect 外部重定向
  • 注意:此阶段不能读取响应,仅用于“路由级”动态干预

示例:将带 v=beta 参数的请求,自动转发到 beta 后端

rewrite_by_lua_block {
    local args = ngx.req.get_uri_args()
    if args.v == "beta" then
        ngx.var.upstream_host = "backend-beta"
        -- 同时清理 v 参数,避免透传
        ngx.req.set_uri_args({v = nil})
    end
}

注意事项与避坑点

动态替换看似简单,但实际部署中容易出错:

  • body_filter_by_lua* 是流式执行,chunk 可能被截断(如 "hello" + "body>"),正则跨 chunk 匹配会失败 → 应避免依赖跨块结构,或启用 lua_http10_buffering off 并结合缓冲逻辑(复杂,一般不推荐)
  • 二进制响应(如图片、PDF)不能直接用 string.gsub,否则会损坏文件 → 必须先判断 ngx.var.content_type,只对 text/*、application/json 等类型处理
  • 替换操作有性能开销,高频大流量场景建议用 ngx.re.gsub(C 实现,比 Lua string.gsub 快数倍)
  • 调试时开启 error_log /path/debug.log debug;,用 ngx.log(ngx.DEBUG, ...) 输出中间值

相关文章

PHP速学视频免费教程(入门到精通)
PHP速学视频免费教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

nginx

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
PixTV官网入口地址合集
PixTV官网入口地址合集

本专题汇总了 PixTV AI 一站式视频创作平台的官方入口与使用教程。无需下载软件,浏览器直接访问即可使用。平台将剧本、图像、视频、声音与剪辑整合在“无限画布”中,接入 GPT Image 2.5、Seedance 2.5 等头部模型。本专题整理了从新建画布、角色锚定、分镜拆分到视频生成与导出的完整操作指南,助你快速上手 AI 短剧与漫剧创作。

2026.10.10

40

15

Kratos框架HTTP与gRPC服务开发教程
Kratos框架HTTP与gRPC服务开发教程

本专题围绕Kratos框架双协议服务开发,涵盖HTTP路由与处理器编写、参数获取、gRPC服务实现与客户端调用、metadata上下文传递、encoding编解码注册、统一响应封装、超时控制与流式响应实现方法。

2026.10.10

20

15

Kratos框架Protobuf接口定义与代码生成合集
Kratos框架Protobuf接口定义与代码生成合集

本专题讲解Kratos框架接口定义体系,涵盖proto编写规范、proto add/client/server生成命令、http注解路由、validate校验、OpenAPI文档生成、跨服务proto复用与兼容性设计。

2026.10.10

0

15

C++虚函数怎么定义和调用
C++虚函数怎么定义和调用

C++虚函数是实现运行时多态的重要机制。本专题从virtual关键字的基本用法入手,介绍基类与派生类之间的函数重写、基类指针调用派生类方法,以及动态绑定的执行过程,帮助初学者掌握虚函数的核心语法。

2026.10.10

20

26

C++类与对象的封装方法教程
C++类与对象的封装方法教程

C++封装是面向对象编程的核心特性之一,通过类将数据与操作数据的函数组织在一起,并利用访问权限控制外部访问。本专题介绍类的定义、成员变量、成员函数以及public、private和protected的使用方法,帮助初学者掌握封装的基本原理。

2026.10.10

20

32

C++构造函数定义与调用方法
C++构造函数定义与调用方法

C++构造函数用于初始化类对象,是面向对象编程的重要基础。本专题从构造函数的定义、声明和调用入手,介绍默认构造函数、带参数构造函数、拷贝构造函数及成员初始化列表,帮助初学者掌握对象创建与初始化的基本方法。

2026.10.10

20

16

Kratos框架零基础入门教程
Kratos框架零基础入门教程

本专题整理Kratos框架入门内容,涵盖Go环境准备、kratos CLI安装升级、new命令创建项目、目录结构分层说明、服务启动与双协议端口、依赖下载报错排查,帮助开发者快速跑通第一个Kratos框架微服务应用。

2026.10.10

20

15

C++条件判断语句怎么写
C++条件判断语句怎么写

C++条件判断是控制程序执行流程的重要基础。本专题介绍if、if-else、else if和switch等常见分支语句,结合条件表达式、比较运算符与代码示例,帮助初学者掌握不同场景下的判断逻辑。

2026.10.10

0

13

C++变量怎么声明和赋值
C++变量怎么声明和赋值

C++变量是编写程序和存储数据的基础。本专题围绕变量声明、定义、初始化、赋值和类型选择等内容展开,帮助初学者理解不同变量的用法,并掌握在实际代码中定义和使用变量的方法。

2026.10.10

20

20

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
phpEnv手册
phpEnv手册

共0课时 | 0人学习

nginx手册
nginx手册

共0课时 | 0人学习

进程与SOCKET
进程与SOCKET

共6课时 | 0.5万人学习