PermalinkPlugin Development - Write custom logic
PermalinkModule
"kong.plugins.<plugin_name>.handler"
Kong allows you to execute custom code at different times in the lifecycle of a
request. To do so, you have to implement one or several of the methods of the
base_plugin.lua
interface. Those methods are to be implemented in a module
at: "kong.plugins.<plugin_name>.handler"
PermalinkAvailable request contexts
Kong allows you to write your code in all of the lua-nginx-module contexts.
Each function to implement in your handler.lua
file will be executed when the
context is reached for a request:
Function name | lua-nginx-module context | Description |
---|---|---|
:init_worker() |
init_worker_by_lua | Executed upon every Nginx worker process’s startup. |
:certificate() |
ssl_certificate_by_lua_block | Executed during the SSL certificate serving phase of the SSL handshake. |
:rewrite() |
rewrite_by_lua_block | Executed for every request upon its reception from a client as a rewrite phase handler. NOTE in this phase neither the api nor the consumer have been identified, hence this handler will only be executed if the plugin was configured as a global plugin! |
:access() |
access_by_lua | Executed for every request from a client and before it is being proxied to the upstream service. |
:header_filter() |
header_filter_by_lua | Executed when all response headers bytes have been received from the upstream service. |
:body_filter() |
body_filter_by_lua | Executed for each chunk of the response body received from the upstream service. Since the response is streamed back to the client, it can exceed the buffer size and be streamed chunk by chunk. hence this method can be called multiple times if the response is large. See the lua-nginx-module documentation for more details. |
:log() |
log_by_lua | Executed when the last response byte has been sent to the client. |
All of those functions take one parameter given by Kong: the configuration of your plugin. This parameter is a simple Lua table, and will contain values defined by your users, according to the schema of your choice. More on that in the next chapter.
Permalinkhandler.lua specifications
The handler.lua
file must return a table implementing the functions you wish
to be executed. In favor of brevity, here is a commented example module
implementing all the available methods:
-- Extending the Base Plugin handler is optional, as there is no real
-- concept of interface in Lua, but the Base Plugin handler's methods
-- can be called from your child implementation and will print logs
-- in your `error.log` file (where all logs are printed).
local BasePlugin = require "kong.plugins.base_plugin"
local CustomHandler = BasePlugin:extend()
-- Your plugin handler's constructor. If you are extending the
-- Base Plugin handler, it's only role is to instantiate itself
-- with a name. The name is your plugin name as it will be printed in the logs.
function CustomHandler:new()
CustomHandler.super.new(self, "my-custom-plugin")
end
function CustomHandler:init_worker()
-- Eventually, execute the parent implementation
-- (will log that your plugin is entering this context)
CustomHandler.super.init_worker(self)
-- Implement any custom logic here
end
function CustomHandler:certificate(config)
-- Eventually, execute the parent implementation
-- (will log that your plugin is entering this context)
CustomHandler.super.certificate(self)
-- Implement any custom logic here
end
function CustomHandler:rewrite(config)
-- Eventually, execute the parent implementation
-- (will log that your plugin is entering this context)
CustomHandler.super.rewrite(self)
-- Implement any custom logic here
end
function CustomHandler:access(config)
-- Eventually, execute the parent implementation
-- (will log that your plugin is entering this context)
CustomHandler.super.access(self)
-- Implement any custom logic here
end
function CustomHandler:header_filter(config)
-- Eventually, execute the parent implementation
-- (will log that your plugin is entering this context)
CustomHandler.super.header_filter(self)
-- Implement any custom logic here
end
function CustomHandler:body_filter(config)
-- Eventually, execute the parent implementation
-- (will log that your plugin is entering this context)
CustomHandler.super.body_filter(self)
-- Implement any custom logic here
end
function CustomHandler:log(config)
-- Eventually, execute the parent implementation
-- (will log that your plugin is entering this context)
CustomHandler.super.log(self)
-- Implement any custom logic here
end
-- This module needs to return the created table, so that Kong
-- can execute those functions.
return CustomHandler
Of course, the logic of your plugin itself can be abstracted away in another
module, and called from your handler
module. Many existing plugins have
already chosen this pattern when their logic is verbose, but it is purely
optional:
local BasePlugin = require "kong.plugins.base_plugin"
-- The actual logic is implemented in those modules
local access = require "kong.plugins.my-custom-plugin.access"
local body_filter = require "kong.plugins.my-custom-plugin.body_filter"
local CustomHandler = BasePlugin:extend()
function CustomHandler:new()
CustomHandler.super.new(self, "my-custom-plugin")
end
function CustomHandler:access(config)
CustomHandler.super.access(self)
-- Execute any function from the module loaded in `access`,
-- for example, `execute()` and passing it the plugin's configuration.
access.execute(config)
end
function CustomHandler:body_filter(config)
CustomHandler.super.body_filter(self)
-- Execute any function from the module loaded in `body_filter`,
-- for example, `execute()` and passing it the plugin's configuration.
body_filter.execute(config)
end
return CustomHandler
PermalinkPlugins execution order
Some plugins might depend on the execution of others to perform some operations. For example, plugins relying on the identity of the consumer have to run after authentication plugins. Considering this, Kong defines priorities between plugins execution to ensure that order is respected.
Your plugin’s priority can be configured via a property accepting a number in the returned handler table:
CustomHandler.PRIORITY = 10
The higher the priority, the sooner your plugin’s phases will be executed in
regard to other plugins’ phases (such as :access()
, :log()
, etc…).
The current order of execution for the bundled plugins is:
Plugin | Priority |
---|---|
bot-detection | 2500 |
cors | 2000 |
jwt | 1005 |
oauth2 | 1004 |
key-auth | 1003 |
ldap-auth | 1002 |
basic-auth | 1001 |
hmac-auth | 1000 |
ip-restriction | 990 |
request-size-limiting | 951 |
acl | 950 |
rate-limiting | 901 |
response-ratelimiting | 900 |
request-transformer | 801 |
response-transformer | 800 |
aws-lambda | 750 |
http-log | 12 |
statsd | 11 |
datadog | 10 |
file-log | 9 |
udp-log | 8 |
request-termination | 7 |
loggly | 6 |
runscope | 5 |
syslog | 4 |
galileo | 3 |
tcp-log | 2 |
correlation-id | 1 |
Next: Store configuration ›