跳到主要内容
版本:3.9.x

添加自定义插件

API7 网关的主要特性之一是其通过插件实现的可扩展性。除了广泛的现有插件外,API7 网关还允许你构建自定义插件,以添加额外功能并通过自定义流程管理 API 流量。通常,你会使用 Lua 编程语言来实现新插件。API7 网关分阶段处理请求,并在请求路由期间的每个阶段执行相关的插件逻辑。

前置条件

  1. 使用 Lua 创建插件

添加自定义插件

  1. 从侧边导航栏选择 Gateway Settings,然后选择 Custom Plugin
  2. 点击 Add Custom Plugin
  3. 在添加自定义插件对话框中,执行以下操作:
  • Plugin Source Code File:上传自定义插件的源代码。
  • Plugin Catalog:选择插件的目录,例如 General
  • Plugin Description:填写插件描述,例如 Replace the response body
  • Plugin Documentation Link:添加插件文档的 URL。
  • Plugin Author:填写插件作者的姓名。
  • Deployed Gateway Group:选择 Select All
  • 点击 Add
  1. 现在你的自定义插件已添加到插件列表中。它可以在 Add Plugin 对话框中被全局规则、服务、路由、消费者或插件选中。

以下是一个交互式演示,提供了添加自定义插件的实践介绍。通过点击并按照步骤操作,你将更好地了解如何在 API7 企业版中使用它。

添加依赖库

从 Dashboard 上传的自定义插件会被注册为一个独立、自包含的插件模块。控制面将其源代码下发到各网关并直接加载到运行时——文件不会写入网关的 Lua 模块搜索路径。因此,上传的自定义插件无法被另一个插件可靠地通过 require() 解析,你也不应把共享库作为自定义插件上传,再让其他插件去 require 它。这种用法初看可能正常,但在网关重启后会失效,因为无法再保证该依赖会先于依赖它的插件被加载。

当多个插件共享辅助代码,或某个插件依赖第三方 Lua 模块或原生(C)库时,应将该依赖安装到网关的包搜索路径上,再在插件中正常 require 它。

将依赖放到 Lua 或 C 路径

网关通过两个搜索路径解析模块:

  • Lua 模块通过 lua_package_path 解析。位于 <dir>/myorg/utils.lua 的文件用 require("myorg.utils") 加载。
  • 原生 Lua/C 模块通过 lua_package_cpath 解析。位于 <dir>/myorg/native.so 的文件用 require("myorg.native") 加载。

你可以使用网关内置路径,也可以使用自定义目录:

  • 内置路径——将文件放到运行时的默认搜索路径下(例如 /usr/local/apisix/ 下),并使路径与你 require 的模块名匹配。

  • 额外路径(推荐)——将你的代码与运行时分开存放,在数据面 config.yaml 中添加你自己的目录:

    apisix:
    extra_lua_path: "/data/lua/?.lua" # 扩展 lua_package_path
    extra_lua_cpath: "/data/clib/?.so" # 扩展 lua_package_cpath

    详见配置参考

备注

通过 LuaJIT FFI 的 ffi.load() 加载的原生库由系统动态链接器解析,而非 lua_package_cpath。这类库应放到系统库路径下(例如 /usr/local/lib),或在网关上设置 LD_LIBRARY_PATH

让网关能访问到这些文件

依赖文件必须在网关启动前存在于每个网关节点上:

  • Kubernetes / Helm——通过卷(例如 ConfigMap 或持久卷)将文件挂载进网关 Pod,并将 extra_lua_path / extra_lua_cpath 指向挂载路径。
  • Docker / Docker Compose——将目录绑定挂载进网关容器。

与由控制面动态下发的自定义插件不同,包搜索路径上的库在网关 worker 启动时加载。新增或修改这些文件后,需要重载或重启网关使其生效。

示例

将共享的辅助函数放到网关路径上的一个普通 Lua 模块中——例如 /data/lua/myorg/base.lua

local _M = {}

function _M.verify(token)
-- 多个插件共用的逻辑
return token ~= nil
end

return _M

在数据面配置中添加该目录:

apisix:
extra_lua_path: "/data/lua/?.lua"

然后在任意自定义插件中 require 它:

local core = require("apisix.core")
local base = require("myorg.base")

-- ...

function _M.access(conf, ctx)
if not base.verify(core.request.header(ctx, "Authorization")) then
return 401
end
end

由于该模块位于包搜索路径上,require("myorg.base") 在每个 worker 上都以相同方式解析,并能在网关重启后继续生效。

附加资源