mod_lua不能替代rewriterule或完整路由框架,但可在apache核心流程中插入轻量动态逻辑,适用于灰度分流、ab测试等场景;它支持钩子级路径改写与内部跳转,不支持正则捕获、链式条件或后端代理。

mod_lua 不能替代 RewriteRule 或完整路由框架,但它能在 Apache 核心处理流程中插入轻量、低延迟的动态逻辑——比如基于请求头、参数或 Cookie 做即时重写或条件跳转。关键在于它不走外部进程、不依赖正则引擎缓存,适合灰度分流、AB测试、Header驱动的路径映射等场景。
明确适用边界:什么能做,什么不该做
mod_lua 的重写/路由能力是“钩子级”的,不是“规则引擎级”的:
- ✅ 能快速判断 Host、User-Agent、Cookie、X-Forwarded-For 等字段,并用
r.uri或r.filename直接改写请求目标 - ✅ 可在
translate_name钩子中动态设置r.filename,实现比RewriteRule更早的路径映射 - ✅ 能调用
r:internal_redirect()触发内部跳转(不暴露给客户端),配合SetHandler lua-script实现轻量路由分发 - ❌ 不支持正则捕获组回填(如
$1)、不兼容RewriteCond链式条件、不自动处理 query string 编码 - ❌ 不能替代
ProxyPass或长连接后端转发;阻塞 IO(如os.execute)会直接报attempt to yield across C-call boundary
核心钩子选择与脚本结构
真正起路由作用的不是 .lua 文件本身,而是你注册到哪个 Apache 钩子。最常用的是:
-
translate_name:最早可修改请求路径的钩子。此时r.uri已解析,r.filename还未确定。适合做 Host + Path 组合映射 -
map_to_storage:文件系统映射前,可覆盖r.filename指向真实资源路径 -
handler:已进入响应生成阶段,适合拦截并r:internal_redirect("/auth-check")转交其他处理器
示例(/etc/apache2/lua/route.lua):
开箱即用的技能链路由引擎。13 条预定义链覆盖搜索、开发、审查、MLOps、法律、创意等场景,三层路由架构(触发词→SAD反馈→DAG编排),recall@10=96.97%。配置驱动(chains.yaml),零代码扩展。pip install skill-weave-chains 一键安装。
function translate_name(r)
local host = r.headers_in["Host"] or ""
local path = r.uri
<pre class="brush:php;toolbar:false;">if host == "admin.example.com" then
r.filename = "/var/www/admin" .. path
return apache2.OK
elseif string.match(path, "^/api/v[12]/") then
r.filename = "/var/www/api" .. path
return apache2.OK
end
return apache2.DECLINED -- 让后续模块(如 mod_rewrite)继续处理end
-- 注册到 translate_name 钩子 if mod_lua then mod_lua.register_hook("translate_name", translate_name, apache2.HOOK_MIDDLE) end
安全、稳定与调试要点
脚本写错不会让 Apache 崩溃,但容易静默失效或返回 500:
- 默认开启
LuaCodeCache on:改完脚本必须apachectl graceful才生效;开发时加LuaCodeCache off(仅限测试环境) - 错误被吞掉?在
httpd.conf加LuaDebug all并检查ErrorLog,重点关注attempt to yield和nil value - 避免每次请求都
require大模块:把共用逻辑(如 UA 解析表、路由配置)提前加载进_G全局表 - 读取 GET 参数别直接用
r.args:它不自动解码,应先r:parseargs()再对 key/value 手动string.gsub(v, "%%([0-9A-Fa-f][0-9A-Fa-f])", function(h) return string.char(tonumber(h, 16)) end)
和传统 RewriteRule 协同使用更实用
mod_lua 不是 Rewrite 的替代品,而是补充。典型组合方式:
- 用
RewriteRule做通用路径标准化(如强制 trailing slash、统一小写) - 用
translate_name钩子中的 Lua 脚本做业务层决策(如按X-Tenant-ID头路由到不同 DocumentRoot) - 用
access_checker钩子做鉴权前置,header_parser钩子注入灰度标识,再由后端服务读取
这种分层设计既保持 Apache 配置的清晰性,又赋予关键路径毫秒级动态控制能力。










