Write plugins in Go

Developing Go plugins

Kong Gateway supports the Go language with the Go PDK, a library that provides Go bindings for Kong Gateway.

Overview

To write a Kong Gateway plugin in Go, you need to:

  1. Define a structure type to hold configuration.
  2. Write a New() function to create instances of your structure.
  3. Add methods to that structure to handle phases.
  4. Include the go-pdk/server sub-library.
  5. Add a main() function that calls server.StartServer(New, Version, Priority).
  6. Compile as an executable with go build.

Note: The Kong Go plugins repository contains example Go plugins.

Configuration

Struct

The plugin you write needs a way to handle incoming configuration data from the data store or the Admin API. You can use a struct to create a schema of the incoming data.

  1. type MyConfig struct {
  2. Path string
  3. Reopen bool
  4. }

Because this plugin will be processing configuration data, you are going to want to control encoding using the encoding/json package. Go fields that start with a capital letter can be exported, making them accessible outside of the current package, including by the encoding/json package. If you want the fields to have a different name in the data store, add tags to the fields in your struct.

  1. type MyConfig struct {
  2. Path string `json:"my_file_path"`
  3. Reopen bool `json:"reopen"`
  4. }

The New() constructor

The plugin must define a function called New. This function should instantiate the MyConfig struct and return it as an interface.

  1. func New() interface{} {
  2. return &MyConfig{}
  3. }

The main() function

Each plugin is compiled as a standalone executable. Include github.com/Kong/go-pdk in the imports list, and add a main() function:

  1. func main () {
  2. server.StartServer(New, Version, Priority)
  3. }

Executables can be placed somewhere in your path (for example, /usr/local/bin). The common -h flag shows a usage help message:

  1. my-plugin -h

Output:

  1. Usage of my-plugin:
  2. -dump
  3. Dump info about plugins
  4. -help
  5. Show usage info
  6. -kong-prefix string
  7. Kong prefix path (specified by the -p argument commonly used in the Kong CLI) (default "/usr/local/kong")

When you run the plugin without arguments, it creates a socket file within the kong-prefix and the executable name, appending .socket. For example, if the executable is my-plugin, the socket file would be /usr/local/kong/my-plugin.socket.

Phase handlers

In Kong Gateway Lua plugins, you can implement custom logic to be executed at various points of the request processing lifecycle. For example, to execute custom Go code during the access phase, create a function named Access with the following function signature:

  1. func (conf *MyConfig) Access (kong *pdk.PDK) {
  2. ...
  3. }

You can implement custom logic during the following phases using the same function signature:

  • Certificate
  • Rewrite
  • Access
  • Response
  • Preread
  • Log

The presence of the Response handler automatically enables the buffered proxy mode.

Version and priority

You can define the version number and priority of execution by declaring the following constants within the plugin code:

  1. const Version = "1.0.0"
  2. const Priority = 1

Kong Gateway executes plugins from highest priority to lowest.

Example configuration

To load plugins using the kong.conf configuration file, you have to map existing Kong Gateway properties to aspects of your plugin. Here are two examples of loading plugins within kong.conf:

  1. pluginserver_names = my-plugin,other-one
  2. pluginserver_my_plugin_socket = /usr/local/kong/my-plugin.socket
  3. pluginserver_my_plugin_start_cmd = /usr/local/bin/my-plugin
  4. pluginserver_my_plugin_query_cmd = /usr/local/bin/my-plugin -dump
  5. pluginserver_other_one_socket = /usr/local/kong/other-one.socket
  6. pluginserver_other_one_start_cmd = /usr/local/bin/other-one
  7. pluginserver_other_one_query_cmd = /usr/local/bin/other-one -dump

The socket and start command settings coincide with their defaults and can be omitted:

  1. pluginserver_names = my-plugin,other-one
  2. pluginserver_my_plugin_query_cmd = /usr/local/bin/my-plugin -dump
  3. pluginserver_other_one_query_cmd = /usr/local/bin/other-one -dump

More information