检查外部依赖

如果你的插件,涉及到一些外部的依赖和三方库,请首先检查一下依赖项的内容。 如果插件需要用到共享内存,需要在 bin/apisix 文 件里面进行申明,例如:

  1. lua_shared_dict plugin-limit-req 10m;
  2. lua_shared_dict plugin-limit-count 10m;
  3. lua_shared_dict prometheus-metrics 10m;
  4. lua_shared_dict plugin-limit-conn 10m;
  5. lua_shared_dict upstream-healthcheck 10m;
  6. lua_shared_dict worker-events 10m;
  7. # for openid-connect plugin
  8. lua_shared_dict discovery 1m; # cache for discovery metadata documents
  9. lua_shared_dict jwks 1m; # cache for JWKs
  10. lua_shared_dict introspection 10m; # cache for JWT verification results

插件本身提供了 init 方法。方便插件加载后做初始化动作。

注:如果部分插件的功能实现,需要在 Nginx 初始化启动,则可能需要在 apisix.lua 文件的初始化方法 http_init 中添加逻辑,并且 可能需要在 bin/apisix 文件中,对 Nginx 配置文件生成的部分,添加一些你需要的处理。但是这样容易对全局产生影响,根据现有的 插件机制,我们不建议这样做,除非你已经对代码完全掌握。

插件命名与配置

给插件取一个很棒的名字,确定插件的加载优先级,然后在 conf/config.yaml 文件中添加上你的插件名。例如 key-auth 这个插件, 需要在代码里指定插件名称(名称是插件的唯一标识,不可重名),在 apisix/plugins/key-auth.lua 文件中可以看到:

  1. local plugin_name = "key-auth"
  2. local _M = {
  3. version = 0.1,
  4. priority = 2500,
  5. type = 'auth',
  6. name = plugin_name,
  7. schema = schema,
  8. }

注:新插件的优先级( priority 属性 )不能与现有插件的优先级相同。另外,优先级( priority )值大的插件,会优先执行,比如 basic-auth 的优先级是 2520 ,ip-restriction 的优先级是 3000 ,所以在每个阶段,会先执行 ip-restriction 插件,再去执行 basic-auth 插件。

conf/config.yaml 配置文件中,列出了启用的插件(都是以插件名指定的):

  1. plugins: # plugin list
  2. - example-plugin
  3. - limit-req
  4. - limit-count
  5. - limit-conn
  6. - key-auth
  7. - prometheus
  8. - node-status
  9. - jwt-auth
  10. - zipkin
  11. - ip-restriction
  12. - grpc-transcode
  13. - serverless-pre-function
  14. - serverless-post-function
  15. - openid-connect
  16. - proxy-rewrite
  17. - redirect

注:先后顺序与执行顺序无关。

特别需要注意的是,如果你的插件有新建自己的代码目录,那么就需要修改 Makefile 文件,新增创建文件夹的操作,比如:

  1. $(INSTALL) -d $(INST_LUADIR)/apisix/plugins/skywalking
  2. $(INSTALL) apisix/plugins/skywalking/*.lua $(INST_LUADIR)/apisix/plugins/skywalking/

配置描述与校验

定义插件的配置项,以及对应的 Json Schema 描述,并完成对 json 的校验,这样方便对配置的数据规 格进行验证,以确保数据的完整性以及程序的健壮性。同样,我们以 key-auth 插件为例,看看他的配置数据:

  1. "key-auth" : {
  2. "key" : "auth-one"
  3. }

插件的配置数据比较简单,只支持一个命名为 key 的属性,那么我们看下他的 Schema 描述:

  1. local schema = {
  2. type = "object",
  3. properties = {
  4. key = {type = "string"},
  5. }
  6. }

同时,需要实现 check_schema(conf) 方法,完成配置参数的合法性校验。

  1. function _M.check_schema(conf)
  2. return core.schema.check(schema, conf)
  3. end

注:项目已经提供了 core.schema.check 公共方法,直接使用即可完成配置参数校验。

确定执行阶段

根据业务功能,确定你的插件需要在哪个阶段执行。 key-auth 是一个认证插件,只要在请求进来之后业务响应之前完成认证即可。 该插件在 rewrite 、access 阶段执行都可以,项目中是用 rewrite 阶段执行认证逻辑,一般 IP 准入、接口权限是在 access 阶段 完成的。

编写执行逻辑

在对应的阶段方法里编写功能的逻辑代码。

编写测试用例

针对功能,完善各种维度的测试用例,对插件做个全方位的测试吧!插件的测试用例,都在 t/plugin 目录下,可以前去了解。 项目测试框架采用的 test-nginx 。 一个测试用例 .t 文件,通常用 _DATA_ 分割成 序言部分 和 数据部分。这里我们简单介绍下数据部分, 也就是真正测试用例的部分,仍然以 key-auth 插件为例:

  1. === TEST 1: sanity
  2. --- config
  3. location /t {
  4. content_by_lua_block {
  5. local plugin = require("apisix.plugins.key-auth")
  6. local ok, err = plugin.check_schema({key = 'test-key'})
  7. if not ok then
  8. ngx.say(err)
  9. end
  10. ngx.say("done")
  11. }
  12. }
  13. --- request
  14. GET /t
  15. --- response_body
  16. done
  17. --- no_error_log
  18. [error]

一个测试用例主要有三部分内容:

  • 程序代码: Nginx location 的配置内容
  • 输入: http 的 request 信息
  • 输出检查: status ,header ,body ,error_log 检查

这里请求 /t ,经过配置文件 location ,调用 content_by_lua_block 指令完成 lua 的脚本,最终返回。 用例的断言是 response_body 返回 “done”,no_error_log 表示会对 Nginx 的 error.log 检查, 必须没有 ERROR 级别的记录。

附上test-nginx 执行流程

根据我们在 Makefile 里配置的 PATH,和每一个 .t 文件最前面的一些配置项,框架会组装成一个完整的 nginx.conf 文件, t/servroot 会被当成 Nginx 的工作目录,启动 Nginx 实例。根据测试用例提供的信息,发起 http 请求并检查 http 的返回项, 包括 http status,http response header, http response body 等。