实现自定义逻辑

本文原文链接:https://docs.konghq.com/1.1.x/plugin-development/custom-logic/

简介

Kong插件允许您在 request/response 的生命周期中的几个入口点注入自定义逻辑(使用 Lua 语言),因为它由Kong代理。为此,必须实现base_plugin.lua 接口的一个或多个方法。这些方法将在命名空间下的模块中实现:kong.plugins。<plugin_name> .handler

Module

  1. kong.plugins.<plugin_name>.handler

可用的请求上下文

插件接口允许您覆盖handler.lua文件中的以下任何方法,以在Kong的执行生命周期的各个入口点实现自定义逻辑:

函数名 LUA-NGINX-MODULE Context 描述
:init_worker() init_worker_by_lua 在每个 Nginx 工作进程启动时执行
:certificate() ssl_certificate_by_lua 在SSL握手阶段的SSL证书服务阶段执行
:rewrite() rewrite_by_lua 从客户端接收作为重写阶段处理程序的每个请求执行。在这个阶段,无论是API还是消费者都没有被识别,因此这个处理器只在插件被配置为全局插件时执行
:access() access_by_lua 为客户的每一个请求而执行,并在它被代理到上游服务之前执行
:header_filter() header_filter_by_lua 从上游服务接收到所有响应头字节时执行
:body_filter() body_filter_by_lua 从上游服务接收的响应体的每个块时执行。由于响应流回客户端,它可以超过缓冲区大小,因此,如果响应较大,该方法可以被多次调用
:log() log_by_lua 当最后一个响应字节已经发送到客户端时执行

所有这些函数都使用一个参数,该参数由Kong在调用时给出:插件的配置。此参数是Lua表,并包含用户根据插件的架构(在schema.lua模块中描述)定义的值。有关插件模式的更多信息将在下一章中介绍。

handler.lua规范

handler.lua文件必须返回一个表,该表实现了您希望执行的函数。为简洁起见,这里有一个注释示例模块,它实现了所有可用的方法:

  1. -- 扩展基本插件处理程序是可选的,因为Lua中没有真正的接口概念,
  2. -- 但是基本插件处理程序的方法可以从子实现中调用,
  3. -- 并将在“error.log”中打印日志(其中打印所有日志)。
  4. local BasePlugin = require "kong.plugins.base_plugin"
  5. local CustomHandler = BasePlugin:extend()
  6. -- 你的插件处理程序的构造函数。
  7. -- 如果要扩展基本插件处理程序,它的唯一作用就是用名称实例化自己。
  8. -- 该名称是您的插件名称,因为它将打印在日志中
  9. function CustomHandler:new()
  10. CustomHandler.super.new(self, "my-custom-plugin")
  11. end
  12. function CustomHandler:init_worker()
  13. -- 最终,执行父实现
  14. -- (将记录您的插件正在进入此上下文)
  15. CustomHandler.super.init_worker(self)
  16. -- 在此实现任何自定义逻辑
  17. end
  18. function CustomHandler:certificate(config)
  19. -- 最终,执行父实现
  20. -- (将记录您的插件正在进入此上下文)
  21. CustomHandler.super.certificate(self)
  22. -- Implement any custom logic here
  23. end
  24. function CustomHandler:rewrite(config)
  25. -- Eventually, execute the parent implementation
  26. -- (will log that your plugin is entering this context)
  27. CustomHandler.super.rewrite(self)
  28. -- Implement any custom logic here
  29. end
  30. function CustomHandler:access(config)
  31. -- Eventually, execute the parent implementation
  32. -- (will log that your plugin is entering this context)
  33. CustomHandler.super.access(self)
  34. -- Implement any custom logic here
  35. end
  36. function CustomHandler:header_filter(config)
  37. -- Eventually, execute the parent implementation
  38. -- (will log that your plugin is entering this context)
  39. CustomHandler.super.header_filter(self)
  40. -- Implement any custom logic here
  41. end
  42. function CustomHandler:body_filter(config)
  43. -- Eventually, execute the parent implementation
  44. -- (will log that your plugin is entering this context)
  45. CustomHandler.super.body_filter(self)
  46. -- Implement any custom logic here
  47. end
  48. function CustomHandler:log(config)
  49. -- Eventually, execute the parent implementation
  50. -- (will log that your plugin is entering this context)
  51. CustomHandler.super.log(self)
  52. -- Implement any custom logic here
  53. end
  54. -- 该模块需要返回创建的表
  55. -- Kong 可以执行这些功能。
  56. return CustomHandler

当然,插件本身的逻辑可以抽象到另一个模块中,并从处理程序模块调用。许多现有的插件在逻辑冗长时已经选择了这种模式,但它是完全可选的:

  1. local BasePlugin = require "kong.plugins.base_plugin"
  2. -- 实际的逻辑是在这些模块中实现的
  3. local access = require "kong.plugins.my-custom-plugin.access"
  4. local body_filter = require "kong.plugins.my-custom-plugin.body_filter"
  5. local CustomHandler = BasePlugin:extend()
  6. function CustomHandler:new()
  7. CustomHandler.super.new(self, "my-custom-plugin")
  8. end
  9. function CustomHandler:access(config)
  10. CustomHandler.super.access(self)
  11. -- 从“access”中加载的模块执行任何函数,
  12. -- 例如,`execute()`并将插件的配置传递给它。
  13. access.execute(config)
  14. end
  15. function CustomHandler:body_filter(config)
  16. CustomHandler.super.body_filter(self)
  17. -- Execute any function from the module loaded in `body_filter`,
  18. -- for example, `execute()` and passing it the plugin's configuration.
  19. body_filter.execute(config)
  20. end
  21. return CustomHandler

有关实际处理程序代码的示例,请参阅Key-Auth插件的源代码

插件开发套件

在这些阶段中实现的逻辑很可能必须与请求/响应对象或核心组件交互(例如访问缓存、数据库……)。Kong提供了一个插件开发套件(简称PSK),一组Lua函数和变量,插件可以使用这些Lua函数和变量来执行各种网关操作,确保它们与将来的Kong版本向前兼容。

当您试图实现一些需要与Kong交互的逻辑时(例如检索请求头、从插件生成响应、记录一些错误或调试信息……),您应该参考插件开发工具包

插件执行顺序

一些插件可能依赖于其他插件的执行来执行一些操作。例如,依赖于消费者身份的插件必须在身份验证插件之后运行。考虑到这一点,Kong定义了插件执行之间的优先级,以确保顺序得到遵守。

你的插件的优先级可以通过一个属性来配置,在返回的handler table 中一个数字:

  1. CustomHandler.PRIORITY = 10

优先级越高,相对于其他插件的阶段(如:access()、:log()等),插件的阶段执行得越快。 已有捆绑插件的当前执行顺序为:

插件 优先级
pre-function +inf
zipkin 100000
ip-restriction 3000
bot-detection 2500
cors 25000
jwt 1005
oauth2 1004
key-auth 1003
ldap-auth 1002
basic-auth 1001
hmac-auth 1000
request-size-limiting 951
acl 950
rate-limiting 901
response-ratelimiting 900
request-transformer 801
response-transformer 800
aws-lambda 750
azure-functions 749
prometheus 13
http-log 12
statsd 11
datadog 10
file-log 9
udp-log 8
tcp-log 7
loggly 6
syslog 4
galileo 3
request-termination 2
correlation-id 1
post-function -1000