官方文档:https://docs.konghq.com/2.1.x/plugin-development/
官方的插件库源码 https://github.com/Kong/kong/tree/master/kong/plugins

查看当前可以使用的插件

  1. http://127.0.0.1:8001/plugins/enabled

插件模板

下载官方插件项目开发模版

  1. git clone https://github.com/Kong/kong-plugin.git

base_plugin

在Kong源码的插件目录中,可以看到有一个base_plugin.lua的文件,该文件里定义了一个基类BasePlugin,以及该基类所拥有的一些方法。所有插件都从基类BasePlugin继承而来,开发者可以根据插件自身的需求选择重写某些方法,这些方法实际上对应了OpenResty 的不同执行阶段。

  1. local Object = require "kong.vendor.classic"
  2. local BasePlugin = Object:extend()
  3. local ngx_log = ngx.log
  4. local DEBUG = ngx.DEBUG
  5. local subsystem = ngx.config.subsystem
  6. function BasePlugin:new(name)
  7. self._name = name
  8. end
  9. function BasePlugin:init_worker()
  10. ngx_log(DEBUG, "executing plugin \"", self._name, "\": init_worker")
  11. end
  12. if subsystem == "http" then
  13. function BasePlugin:certificate()
  14. ngx_log(DEBUG, "executing plugin \"", self._name, "\": certificate")
  15. end
  16. function BasePlugin:rewrite()
  17. ngx_log(DEBUG, "executing plugin \"", self._name, "\": rewrite")
  18. end
  19. function BasePlugin:access()
  20. ngx_log(DEBUG, "executing plugin \"", self._name, "\": access")
  21. end
  22. function BasePlugin:header_filter()
  23. ngx_log(DEBUG, "executing plugin \"", self._name, "\": header_filter")
  24. end
  25. function BasePlugin:body_filter()
  26. ngx_log(DEBUG, "executing plugin \"", self._name, "\": body_filter")
  27. end
  28. elseif subsystem == "stream" then
  29. function BasePlugin:preread()
  30. ngx_log(DEBUG, "executing plugin \"", self._name, "\": preread")
  31. end
  32. end
  33. function BasePlugin:log()
  34. ngx_log(DEBUG, "executing plugin \"", self._name, "\": log")
  35. end
  36. return BasePlugin

插件目录结构
kong插件安装目录在/usr/local/share/lua/5.1/kong/plugins/ 目录下

其中kong/plugins 插件的标准目录树.
一个完整的插件目录结构如下:

  1. complete-plugin
  2. ├── api.lua
  3. ├── daos.lua
  4. ├── handler.lua
  5. ├── migrations
  6. ├── cassandra.lua
  7. └── postgres.lua
  8. └── schema.lua

各模块的功能如下:

模块名 是否必须 描述
api.lua 定义可在Admin API中使用的插件endpoints列表
daos.lua 数据层相关,当插件需要访问数据库时配置,这些dao是插件所需的自定义实体的抽象
handler.lua 插件的主要逻辑,每个功能都应由Kong在请求/连接生命周期的所需时刻运行
migrations/*.lua 插件依赖的数据表结构,启用了 daos.lua 时需要定义
schema.lua 插件的配置参数定义,主要用于 Kong 参数验证

其中handler.lua和schema.lua是必须的,一个简单的插件只需要包含这两个lua文件即可。handler.lua负责实现BasePlugin的子类及对应方法,完成插件主逻辑。schema.lua定义了插件所需的用户自定义参数。

自定义插件配置

在/etc/kong/kong.conf文件中你可以找到下面这段
plugins = bundled
kong 插件开发 - 图1

plugins = bundled,my-custom-plugin # your plugin name here


自定义插件的命名个规则为 kong.plugins..
kong 插件开发 - 图2
也就是说当你在plugins属性后面添加了你自己的plugin name之后, kong会尝试加载以kong.plugins.my-custom-plugin.命名的lua模块
还记得一开始提到的两个必要模块名么, 所以你的模块应该类似 kong.plugins.my-custom-plugin.handler
kong 插件开发 - 图3

加载插件路径


还是/etc/kong/kong.conf, 其中属性 lua_package_path 可以用来指定存放自定义插件的路径
kong 插件开发 - 图4
官方文档中这样描述这个配置
kong 插件开发 - 图5
也就是说如果你配置
lua_package_path = /usr/local/custom/?.lua;;
那么你的handler.lua文件要放在

  1. /usr/local/custom/kong/plugins/<plugin-name>/handler.lua

配置文件修改

配置文件修改很方便, 只需要增加插件目录, 并启用插件名称即可:
vim /etc/kong/kong.conf
修改内容:

  1. # 添加自定义插件工作目录
  2. lua_package_path = /opt/share/?.lua;;
  3. # 启用插件: hello-plugin
  4. # bundled: 表示Kong, 自带插件
  5. plugins = bundled, hello-plugin

其中/opt/share/的完整目录结构是/opt/share/kong/plugins/hello-plugin

参考

https://github.com/qianyugang/kong-docs-cn
https://github.com/MyRong12138/change-url
https://www.lijiaocn.com/%E9%A1%B9%E7%9B%AE/2018/11/09/kong-features-07-write-plugins.html
https://github.com/lampnick/kong-rate-limiting-golang
http://libaibai.net/node/302
http://blueskykong.com/2019/09/04/kong3/
https://cloud.tencent.com/developer/article/1653713