kong框架的插件(一)

一、什么时kong的插件

 在kong官方定义:

Kong Gateway is a Lua application designed to load and execute modules, which we commonly refer to as plugins. Plugins provide advanced functionality and extend the use of the Kong Gateway, allowing you to add more features to your implementation.

Kong provides a set of standard Lua plugins that get bundled with Kong Gateway and Konnect. The set of plugins you have access to depends on your license tier.

You can also develop custom plugins, adding your own custom functionality to Kong Gateway.

  可以看出,插件机制是kong用来实现功能的核心,并可以根据业务需要实现自己的插件。

二、自定义插件

2.1、自定义插件的目录结构

基本插件模块:

plugins
├── my-plugin
│   ├── handler.lua    
│   └── schema.lua  

  • handler模块:插件的核心模块。它提供了一组接口,需要用户自定义实现,其中每个方法都会在请求和连接生命周期中的指定时间点运行。
  • schema模块:该模块定义了配置型的规则和格式,会对用户输入的数据进行校验。

高级插件模块:

header-plugin
├── api.lua   
├── daos.lua
├── handler.lua
├── migrations
│   ├── init.lua
│   └── 000_base_header_plugin.lua
└── schema.lua

插件模块是否必填描述
api        其对应文件定义了插件在Admin API中暴露的端点。用户可以使用这些接口与插件中的实体数据进行交互。
daos        其对应文件定义了插件需要用到的表结构。
handler        插件的核心模块,它提供了一组接口,需要用户自定义实现。
migrations/xxx        其对应文件定义了插件数据库迁移指令。该模块仅在用户使用数据库启动模块时才生效。
schema        其对用文件定义了插件配置项的规则和格式。该模块会对用户输入的数据进行校验。
2.2、实现自定义逻辑

        在Kong Gateway中,插件逻辑(Plugin Logic)被设计用来在HTTP请求、TCP流以及Kong Gateway本身生命周期的关键点执行特定的操作。

2.2.1、请求上下文
  1. http子模块对应HTTP和HTTPS请求响应。
表1 http子模块
函数名对应lua-nginx-module挂载点描述
:init_worker()init_worker        在每个Nginx工作进程启动时执行
:certificate()ssl_certificate        在SSL握手阶段执行
:rewrite()rewrite        在重写请求路径时执行。注意,此处Kong网关还没有识别到服务实体和消费者实体,所以只有定义在全局的插件才会执行
:access()access        在客户端请求被代理到上游服务之前执行
:header_filter()header_filter        在接收到上有服务发送的所有响应头内容时执行
:body_filter()body_filter        在接收到上有服务发送的响应体内容时执行。如果响应体过大,会被切分成多个块。所以,对于一个请求,该方法可能会被多次调用。
:log()log        在最后一个响应字节发送到客户端时执行。

      2.stream子模块对应TCP流

表2 stream子模块

函数名对应lua-nginx-module挂载点描述
:init_worker()init_worker        在每个Nginx工作进程启动时执行
:preread()preread        在每次连接时执行一次
:log()log        在最后一个响应字节发送到客户端时执行。

        除init_worker方法外,所有方法在调用时都可以接受一个参数。该参数是一个Table对象,之中包含用户自定义字段的值。字段属性有插件配置项约束。

2.2.2、handler模块规范

        handler模块返回一个Table对象,其中包含所有用户希望执行的方法。示例如下:

-- 插件模板中的扩展方法都是可选的,Lua中没有真正的接口概念
-- 但是Base Plugin handler的方法可以从子实现中调用,
local BasePlugin = require "kong.plugins.base_plugin"
local CustomHandler = BasePlugin:extend()

-- 用户自定义handler模块的构造函数
-- 如果想要扩展handler模块,可自定义模块名称,此处为my-custompligin,并实例化 
function CustomHandler:new()
  CustomHandler.super.new(self, "my-custom-plugin")
end

function CustomHandler:init_worker() 
  -- 执行父方法
  CustomHandler.super.init_worker(self)
  -- 在此实现任何自定义逻辑
end


function CustomHandler:certificate(config) 
    -- 执行父方法
    CustomHandler.super.certificate(self)
    -- 在此实现任何自定义逻辑
end

function CustomHandler:rewrite(config) 
    -- 执行父方法
  CustomHandler.super.rewrite(self)
    -- 在此实现任何自定义逻辑
end

function CustomHandler:access(config) 
  -- 执行父方法
  CustomHandler.super.access(self) 
  -- 在此实现任何自定义逻辑
end

function CustomHandler:hander_filter(config) 
  -- 执行父方法
  CustomHandler.super.hander_filter(self) 
  -- 在此实现任何自定义逻辑
end

function CustomHandler:body_filter(config)
  -- 执行父方法 
  CustomHandler.super.body_filter(self) 
  -- 在此实现任何自定义逻辑
end

function CustomHandler:log(config) 
  -- 执行父方法
  CustomHandler.super.log(self) 
  -- 在此实现任何自定义逻辑
end

return CustomHandler

        当然,我们也可以将插件的实现逻辑抽象到另一个文件中,然后在handler模块中调用这些方法。

local BasePlugin = require "kong.plugins.base_plugin"
-- 实际的逻辑是在以下这些模块中实现的
local access= require "kong.plugins.my-custom-plugin.access"
local bodu_filter = require "kong.plugins.my-custom-plugin.body_filter"

local CustomHandler = BasePlugin:extend()

-- 用户自定义handler模块的构造函数
-- 如果想要扩展handler模块,可自定义模块名称,此处为my-custompligin,并实例化 
function CustomHandler:new()
  CustomHandler.super.new(self, "my-custom-plugin")
end

function CustomHandler:access(config) 
  -- 执行父方法
  CustomHandler.super.access(self) 
  -- 用户可以调用access模块中的任何方法,实例中调用了execute方法,并将config作为入参
  access.execute(config)
end


function CustomHandler:body_filter(config)
  -- 执行父方法 
  CustomHandler.super.body_filter(self) 
  -- 用户可以调用body_filter模块中的任何方法,实例中调用了execute方法,并将config作为入参
  body_filter.execute(config)
end


return CustomHandler
2.2.3、插件的执行顺序

        插件和插件之间有时会存在依赖关系,例如依赖于消费者身份验证的插件必须在鉴权插件之后执行。

        用户可以通过配置插件的优先级属性来更改插件的执行顺序。方式是在handler模块返回的Table对象中加入优先级字段,例如:

CustomHandler.PRIORITY = 10

        优先级属性值越高的插件相对于其他插件执行得越早。

2.3、插件的配置项(schema)

        通常情况下,用户定义的配置项需要满足插件使用者的要求。插件的配置项会存储在数据库中。当插件执行时,kong网关负责获取这些数据,并将它们传递给handler模块。

        在kong网关中,配置项是一个Table对象,我们称之为schema。用户可以在启用插件时通过Admin API传入这些键-值对。

        用户在调用Admin API时,kong网关会根据schema自动对输入的配置项进行校验。

2.3.1、schema模块规范

        该模块和handler模块类似,也是返回一个Table对象,之中包含自定义插件配置项的属性信息,如表3所示。

表3 自定义插件配置项的属性信息
属性名数据类型描述
namestring插件名称,例如key-auth
fieldstable字段详情
entity_checksfunction校验规则

        所有插件默认继承表4所示的属性。

schema.lua文件示例:

local typedefs = require "kong.db.schema.typedefs"

return {
    -- 插件名称
    name = "CunstomHandler",
    -- 字段详情
    fields = {
        {
            -- 这个插件的作用域只能在服务或者路由上
            consumer = typedefs.no_consumer
        },
        {
            -- 这个插件仅适用于HTTPS或者HTTP协议
            protocols = typedefs.protocols_http
        },
        {
            config = {
                type = "recode",
                fields = {
                    -- 自定义配置文件 schema
                },
            },
        },
    },
    -- 校验规则
    entity_checks = {
        -- 自定义校验规则
    }
}

schema常见属性规则,见表5所示。

表5 常见的属性规则
属性规则描述
type属性类型
required属性是否可选
default属性的默认值
elementsarray或set格式的元素类型
keysmap格式的key元素类型
valuesmap格式的value元素类型
fieldsrecode格式的元素类型

        具体的schema说明可以参考:typedefs.luaThe Core Schemas官方文档,key-auth插件的schema模块如下所示:

local typedefs = require "kong.db.schema.typedefs"


return {
  name = "key-auth",
  fields = {
    { consumer = typedefs.no_consumer },
    { protocols = typedefs.protocols_http },
    { config = {
        type = "record",
        fields = {
          { key_names = { description = "Describes an array of parameter names where the plugin will look for a key. The key names may only contain [a-z], [A-Z], [0-9], [_] underscore, and [-] hyphen.", type = "array",
              required = true,
              elements = typedefs.header_name,
              default = { "apikey" },
          }, },
          { hide_credentials = { description = "An optional boolean value telling the plugin to show or hide the credential from the upstream service. If `true`, the plugin strips the credential from the request.", type = "boolean", required = true, default = false }, },
          { anonymous = { description = "An optional string (consumer UUID or username) value to use as an “anonymous” consumer if authentication fails. If empty (default null), the request will fail with an authentication failure `4xx`.", type = "string" }, },
          { key_in_header = { description = "If enabled (default), the plugin reads the request header and tries to find the key in it.", type = "boolean", required = true, default = true }, },
          { key_in_query = { description = "If enabled (default), the plugin reads the query parameter in the request and tries to find the key in it.", type = "boolean", required = true, default = true }, },
          { key_in_body = { description = "If enabled, the plugin reads the request body. Supported MIME types: `application/www-form-urlencoded`, `application/json`, and `multipart/form-data`.", type = "boolean", required = true, default = false }, },
          { run_on_preflight = { description = "A boolean value that indicates whether the plugin should run (and try to authenticate) on `OPTIONS` preflight requests. If set to `false`, then `OPTIONS` requests are always allowed.", type = "boolean", required = true, default = true }, },
        },
    }, },
  },
}

        这样,开发者在handler模块的access方法中就可以直接使用schema模块中定义的配置项。

function   Customhandler:access(config)
    Customhandler.super.access(self)

    kong.log.inspect(config.key_name)
    kong.log.inspect(config.hide_credentials)
end

参考文献:、

  1. 《Kong网关 --入门、实战与进阶》
  2.  Kong官方文档
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值