资讯动态

Apache APISIX Script(脚本)机制详解:在 Route 上直接运行自定义 Lua 代码

发布时间:2026/9/21 22:02:54 来源:尧图企业网站定制
API网关后端云原生微服务【免费下载链接】apisixThe Cloud-Native API Gateway and AI Gateway项目地址https://gitcode.com/gh_mirrors/api/apisix点击查看免费下载Apache APISIX 的 Script 允许你在 Route 上直接绑定一段自定义 Lua 代码并在 HTTP 请求/响应生命周期中自动执行无需编写完整插件。本文以官方术语文档 script.md 为主体结合 apisix/script.lua、apisix/init.lua 与测试用例 t/script/script.t讲解 Script 的配置格式、执行阶段、与 Plugin 的互斥关系及其底层实现原理。什么是 ScriptScript脚本是 APISIX 提供的一种轻量级扩展机制它允许你编写任意 Lua 代码或者直接调用现有插件并将这段代码在 HTTP 请求/响应生命周期中执行。与需要创建独立文件、注册 schema、实现多阶段回调的完整插件相比Script 的优势在于一段 Lua 代码可以直接以字符串形式内嵌在 Route 配置中随配置下发即生效适合快速实现定制化的请求处理逻辑。一个 Script 配置可以直接绑定到 Route 上即把script字段直接写入 Route 的配置对象中。Script 与 Plugin 的关系互斥且优先Script 与 Plugin 之间是互斥关系且Script 先于 Plugin 执行。这意味着一旦 Route 配置了 Script该 Route 上配置的 Plugin 将不会被执行。这一点在 apisix/schema_def.lua 的 Route schema 中得到了强制保证Route 的allOf要求script必须与uri或uris同时出现见 apisix/schema_def.lua#L739-L740同时not约束规定script不能与plugins或plugin_config_id同时出现见 apisix/schema_def.lua#L742-L747从配置校验层面直接杜绝了二者共存。在运行时这一互斥逻辑体现在 apisix/init.lua 的common_phase函数中见 apisix/init.lua#L529-L544local function common_phase(phase_name) local api_ctx ngx.ctx.api_ctx if not api_ctx then return end local global_rules, conf_version apisix_global_rules.global_rules() plugin.run_global_rules(api_ctx, global_rules, conf_version, phase_name) if api_ctx.script_obj then script.run(phase_name, api_ctx) return api_ctx, true end return plugin.run_plugin(phase_name, nil, api_ctx) end可以看到一旦请求上下文api_ctx.script_obj存在说明该 Route 配置了 ScriptAPISIX 会直接调用script.run执行脚本并return提前退出跳过后续的plugin.run_plugin。这就是配置了 Script 后Route 上的 Plugin 不再执行的实现依据。同样在http_access_phase中见 apisix/init.lua#L912-L915if route.value.script then script.load(route, api_ctx) plugin.run_global_rules(api_ctx, global_rules, conf_version, access) script.run(access, api_ctx) else -- 正常走 plugin.filter / plugin.run_plugin 逻辑 end当 Route 带script字段时请求处理走 Script 分支否则才走标准插件过滤与执行流程。测试验证测试用例 t/script/script.t 对该互斥行为做了完整验证TEST 1创建一个绑定example-plugin插件的 ServiceTEST 2创建一个同时绑定service_id和script的 Routeuri: /hello确认带 script 的 Route 可以成功创建并绑定 ServiceTEST 3请求/hello断言错误日志中出现了loaded script_obj: {access:function: 0x...}证明脚本已加载执行同时断言没有出现plugin rewrite phase, conf: {i:1}证明 Service 上配置的 Plugin 未被执行。--- error_log eval qr/loaded script_obj: \{access:function: 0x[\w]\}/ --- no_error_log eval qr/plugin rewrite phase, conf: \{i:1\}/Script 的执行阶段Script 拥有执行阶段phase的概念支持以下四个阶段系统会在 Script 中自动调用对应的阶段函数阶段说明access访问控制阶段在请求被转发给上游之前执行常用于鉴权、改写请求等header_filter响应头过滤阶段在向上游返回响应头之前执行body_filter响应体过滤阶段在处理响应体时执行log日志记录阶段在请求处理完成后执行常用于记录日志Script 通过约定的函数名来定义各阶段逻辑脚本返回一个 table其中以_M.access、_M.header_filter、_M.body_filter、_M.log等命名的函数会被系统自动识别并在对应阶段执行。apisix/script.lua 中的run函数见 apisix/script.lua#L41-L56展示了阶段调度的核心逻辑function _M.run(phase, api_ctx) local obj api_ctx and api_ctx.script_obj if not obj then core.log.error(missing loaded script object) return api_ctx end core.log.info(loaded script_obj: , core.json.delay_encode(obj, true)) local phase_func obj[phase] if phase_func then phase_func(api_ctx) end return api_ctx end即按当前阶段名phase从脚本对象中取出对应的函数若存在则调用并传入api_ctx请求上下文作为参数。基本配置示例官方文档给出了一个最简配置在 Route 中通过script字段写入一段返回 table 的 Lua 代码字符串{ ... script: local _M {} \n function _M.access(api_ctx) \n ngx.log(ngx.INFO,\hit access phase\) \n end \nreturn _M }该脚本定义了一个access阶段函数在访问阶段打印一条hit access phase的 INFO 日志。注意script字段的值为一段完整的 Lua 代码字符串其中换行符需要使用\n转义JSON 字符串中。完整的多阶段脚本示例测试目录中的 t/script/script_test.lua 给出了一个覆盖全部四个阶段的脚本示例可作为参考模板local core require(apisix.core) local _M {} function _M.access(api_ctx) core.log.warn(hit access phase) end function _M.header_filter(ctx) core.log.warn(hit header_filter phase) end function _M.body_filter(ctx) core.log.warn(hit body_filter phase) end function _M.log(ctx) core.log.warn(hit log phase) end return _M可以看到脚本的基本结构为创建并返回一个 table_M在 table 上按阶段名定义access/header_filter/body_filter/log等函数每个函数接收api_ctx请求上下文作为唯一参数最后return _M返回该对象。_M.access(api_ctx)中api_ctx即 APISIX 的请求上下文对象ngx.ctx.api_ctx通过它可以访问请求信息、响应信息、路由/上游匹配结果等数据与插件中使用的api_ctx是同一对象。通过 Admin API 配置 Script下面是一个完整的实战示例通过 Admin API 创建一个带 Script 的 Route。参照 t/script/script.t 中 TEST 2 的写法curl http://127.0.0.1:9180/apisix/admin/routes/1 \ -H X-API-KEY: $admin_key -X PUT -d { uri: /hello, script: local _M {} \n function _M.access(api_ctx) \n ngx.log(ngx.INFO,\hit access phase\) \n end \nreturn _M }配置说明uri路由匹配规则此处匹配/hello路径scriptLua 代码字符串定义各阶段逻辑Route 的 schema 要求script必须与uri或uris同时出现见 apisix/schema_def.lua#L739-L740二者缺一不可。配置成功HTTP 201/200后请求/hello时 APISIX 会加载并执行该脚本在 access 阶段打印 INFO 日志。若脚本语法错误apisix/script.lua 的load函数见 apisix/script.lua#L26-L38会抛出failed to load script错误local loadfun, err loadstring(script, route# .. route.value.id) if not loadfun then error(failed to load script: .. err .. script: .. script) return nil end api_ctx.script_obj loadfun()脚本通过loadstring编译源码块名标记为route#route_id便于定位错误来源编译成功后执行loadfun()得到脚本对象存入api_ctx.script_obj供各阶段调用。Script 字段的 Schema 约束从 apisix/schema_def.lua 可以看到 Route 与 Service 中的script字段约束见 apisix/schema_def.lua#L675 与 apisix/schema_def.lua#L767script {type string, minLength 10, maxLength 102400},约束值说明typestring脚本必须是字符串minLength10脚本字符串最短 10 个字符maxLength102400脚本字符串最长 102400 字符约 100KB防止超大脚本此外源码注释表明该字段用于 dashboard 的插件编排The script fields below are used by dashboard for plugin orchestration即 Script 机制与 APISIX Dashboard 的可视化编排能力紧密相关。需要特别注意的是script字段同时存在于 Route 与 Service 的 schema 中即 Script 也可以配置在 Service 层测试 t/script/script.t 的 TEST 2 即演示了带 script 的 Route 绑定带 plugin 的 Service的场景最终 Route 上的 Script 生效、Service 上的 Plugin 被跳过互斥约束script不能与plugins/plugin_config_id同时出现在同一对象上见 apisix/schema_def.lua#L742-L747由于 Schema 在配置写入阶段即完成校验非法组合如同时配置 script 和 plugins会在 Admin API 返回 400 错误而非运行时报错。使用建议与限制结合官方文档与源码实现使用 Script 时有几点值得注意适合快速、轻量的定制逻辑一段内嵌 Lua 字符串即可实现阶段钩子无需创建插件文件、注册 schema、走插件热加载流程适合原型验证或少量定制与插件互斥Script 一旦启用Route或 Service上的 Plugin 全部失效。若需要同时使用插件能力如限流、鉴权应改用 Plugin 方案或通过 Global Rules 等方式补充注意 Lua 字符串转义通过 Admin APIJSON写入脚本时换行符需写成\n引号需转义否则会导致 JSON 解析失败或脚本编译错误执行阶段有限Script 目前只支持access、header_filter、body_filter、log四个阶段不支持rewrite、preread、balancer等插件可用的全部阶段若需要更完整的阶段覆盖应编写正式插件全局规则仍会执行从 apisix/init.lua#L536 与 apisix/init.lua#L914 可以看出Global Rules全局规则在 Script 分支中仍会被执行因此可以通过 Global Rules 在 Script 场景下补充通用逻辑脚本长度受限单个脚本字符串上限约 100KB超长逻辑应考虑拆分为正式插件模块。总体而言Script 是 APISIX 在完整插件与无扩展之间提供的一条轻量路径其加载与调度实现集中在 apisix/script.lualoadrun两个核心函数互斥语义由 apisix/schema_def.lua 的 Schema 校验与 apisix/init.lua 的运行时分支共同保证行为可由 t/script/script.t 中的测试用例完整验证。赞分享API网关后端云原生微服务【免费下载链接】apisixThe Cloud-Native API Gateway and AI Gateway项目地址https://gitcode.com/gh_mirrors/api/apisix点击查看免费下载相关推荐Apache APISIX Script 机制深度解析在 Route 上编写 Lua 脚本并接管请求生命周期Apache APISIX Script 机制深度解析在 Route 上编写 Lua 脚本并接管请求生命周期 Apache APISIX 的 Script 特后端微服务云原生Apache APISIX Script 脚本机制详解在路由上执行任意 Lua 逻辑并与 Plugin 的互斥关系Apache APISIX Script 脚本机制详解在路由上执行任意 Lua 逻辑并与 Plugin 的互斥关系 本篇文章以 Apache APISIX 的API网关后端云原生微服务Apache APISIX Script 完全指南在路由上执行 Lua 脚本与多阶段钩子Apache APISIX Script 完全指南在路由上执行 Lua 脚本与多阶段钩子 Script 是 Apache APISIX 提供的一种轻量级定制机后端微服务云原生创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价