20 Lines of JavaScript to Create a Kong Gateway Plugin
Tags: apigateway, javascript, plugins, tutorial
Published: 2021-09-02 18:16:01

---
title: 20 Lines of JavaScript to Create a Kong Gateway Plugin
published: True
tags: APIGateway,javascript,plugins,tutorial
canonical_url: https://konghq.com/blog/kong-gateway-plugin-javascript/
---

We recently sat down to discuss the language for the next [Kong Gateway](https://konghq.com/kong/) Plugin Development Kit (PDK). Given the number of JavaScript developers in the world and the variety of libraries and debugging tools available, there was only one logical choice. I’m excited to share that with the [Kong Gateway (OSS) 2.4 release](https://konghq.com/blog/kong-gateway-oss-2-4-released/), that functionality is now available to you all!

To show the power of the new [JavaScript PDK](https://github.com/Kong/kong-js-pdk), we’re going to implement a plugin that adds [X-Clacks-Overhead](https://xclacksoverhead.org/home/about), a non-standardized HTTP header based on the work of [Terry Pratchett](https://en.wikipedia.org/wiki/Terry_Pratchett) to all responses.

## Bootstrapping Your Development Environment

The JavaScript plugin support in Kong Gateway works by running a Node.js server on the same machine as Kong Gateway and passing messages back and forth using `msgpack`.

This means that we need a development environment that can run both the Kong Gateway and a Node.js process. You can configure this on your local machine, but to make things easier, I’ve put together a `docker`-based environment for you to use.

It might take a minute or two to download the images and build our Node.js environment. I recommend running it now in the background as you keep reading:

```
$ git clone https://github.com/Kong/docker-kong-js-pdk
$ cd kong-js-pdk-dev
$ docker-compose build
```

## Creating Your First Plugin

The configuration provided in the environment we created reads all plugins from the `plugins` directory. It’s currently empty as we have not created our first plugin yet.

The JavaScript PDK uses the name of the JS file as the name of the plugin. Let’s go ahead and create a file called `clacks.js` in the `plugins` directory with the following contents:

```
class ClacksPlugin {
  async access(kong) {
    await kong.response.setHeader(`X-Clacks-Overhead`, "GNU Terry Pratchett");
  }
}

module.exports = {
  Plugin: ClacksPlugin,
  Version: "0.1.0"
};
```

The `kong` object passed into the `access` method is an instance of the JavaScript PDK provided by the plugin server. This means that we do not need to require `kong-pdk` in our plugins, as it is automatically made available.

There are five phases available for HTTP requests in the life-cycle of a Kong Gateway request:

-`certificate` – Executed once per request when the connection is SSL/TLS enabled
-`rewrite` – Performed before the API gateway does any routing
-`access` – All routing is done, and the plugin knows which service the request is bound to. This is the last phase before the API gateway makes a request to upstream
-`response` – Allows you to manipulate the response from the upstream. Implementing this phase has a performance penalty as it enables request buffering
-`log` – Executed after the request has been completed

## Enable the Plugin

The environment we’re running uses Kong’s [declarative config](https://docs.konghq.com/gateway-oss/2.4.x/db-less-and-declarative-config/#what-is-declarative-configuration) capability. That means that we need to update the config file to enable our new plugin. Open up `config/kong.yml`, and you should see a service defined that proxies to mockbin.org:

```
services:
  - name: example-service
    url: https://mockbin.org
```

As our file name was `clacks.js`, our plugin will be called `clacks`. Let’s enable the plugin in the definition now:

```
services:
  - name: example-service
    url: https://mockbin.org
    plugins:
      - name: clacks
```

Kong Gateway only allows you to use plugins that are on an allowlist for security purposes, so we’ll also need to add `clacks` to that list. Open up `docker-compose.yml` and edit the value of `KONG_PLUGINS` so that it looks like the following:

```
KONG_PLUGINS: bundled,clacks
```

## Making a Request

At this point the [API gateway](https://konghq.com/learning-center/api-gateway/) is ready to run our new plugin, so let’s go ahead and start it:

```
$ docker-compose up
```

The `docker-compose.yml` file forwards the API gateway port to our local machine. That means we can make requests to `localhost:8000` to test our service.

```
$ curl -I localhost:8000

HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
Connection: keep-alive
X-Clacks-Overhead: GNU Terry Pratchett
...snip...
```

I can see the `X-Clacks-Overhead` header in the response, which means that our plugin works as intended!

## Making It Configurable

The custom JavaScript plugin we built today is a simple plugin that does one thing and does it well. I want to take a moment to show you how you can make that behavior customizable using plugin configuration too.

There is an ongoing discussion based on [RFC 6648](https://tools.ietf.org/html/rfc6648) about if custom headers need an `X-` prefix. Let’s make our plugin configurable so that people can decide if they want to use the `X-` prefix.

Plugin configuration is controlled using the `Schema property` in `module.exports` at the end of `clacks.js`. Let’s add an entry to define a `use_prefix` option that’s a boolean with a default value of `true`:

```
module.exports = {
  Plugin: ClacksPlugin,
  Schema: [{ use_prefix: { type: "boolean", default: true } }],
  Version: "0.1.0"
};
```

Any configuration provided to the plugin is passed in using the `constructor`. Let’s go ahead and capture that in `clacks.js` so that we can use it in our `access` method and update `access` so that it only adds the `X-` prefix if `use_prefix` is true:

```
class ClacksPlugin {
  constructor(config) {
    this.config = config;
  }

  async access(kong) {
    const prefix = this.config.use_prefix ? "X-" : "";
    await kong.response.setHeader(
    `${prefix}Clacks-Overhead`,
    "GNU Terry Pratchett"
    );
  }
}
```

If we run our plugin now, it will behave the same way as it did with a hardcoded `X-` prefix. Let’s update our API gateway config in `config/kong.yml` to set `use_prefix` to `false`.

```
services:
  - name: example-service
    url: https://mockbin.org
    plugins:
      - name: clacks
        config:
          use_prefix: false
```

If we restart our API gateway by pressing `Ctrl+C` then running `docker-compose up` again, we should now be able to make a request to `localhost:8000` and see `Clacks-Overhead` header without the `X-` prefix:

```
$ curl -I localhost:8000

HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
Connection: keep-alive
Clacks-Overhead: GNU Terry Pratchett
...snip...
```

## Conclusion

Just 20 lines of Javascript, and we have a working Kong Gateway plugin, complete with configuration options!

What we’ve built together is a trivial plugin, but using the environment provided and what you’ve learned about Kong’s configuration, you can go ahead and build plugins to your heart’s content.

**If you’re looking for more plugin examples, take a look at some demo plugins:**

- [Convert GitHub API responses from JSON to YAML](https://github.com/Kong/docker-kong-js-pdk/blob/69babbea0a34b4d8284e3c6eb978d979ae55bd71/plugins/json-to-yaml.js) ([config](https://github.com/Kong/docker-kong-js-pdk/blob/with-sample-plugins/config/kong.yml#L5-L12))
- [Extract a Pokemon evolution chain from PokeAPI](https://github.com/Kong/docker-kong-js-pdk/blob/with-sample-plugins/plugins/pokemon-evolution.js) ([config](https://github.com/Kong/docker-kong-js-pdk/blob/with-sample-plugins/config/kong.yml#L13-L20))

**If you have any questions, post them on** [**Kong Nation**](https://discuss.konghq.com/) **.**

To stay in touch, join the [Kong Community](https://konghq.com/community/).

**Once you’ve successfully set up a custom Kong plugin with JavaScript, you may find these other tutorials helpful:**

- [How to Use the Kong Gateway JWT Plugin for Service Authentication](https://konghq.com/blog/jwt-kong-gateway)
- [4 Steps to Authorizing Services With the Kong Gateway OAuth2 Plugin](https://konghq.com/blog/kong-gateway-oauth2/)
- [Getting Started With Kuma Service Mesh](https://konghq.com/blog/getting-started-kuma-service-mesh/)

[![Visit Kong Hub - Extend Kong with 100+ powerful plugins, modules, and integrations](https://konghq.com/wp-content/themes/konghq/assets/img/cta-shortcode/kong-hub.jpg)](https://docs.konghq.com/hub/)

The post [Building a Kong Gateway Plugin with JavaScript](https://konghq.com/blog/kong-gateway-plugin-javascript/) appeared first on [KongHQ](https://konghq.com).