<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Kong</title>
    <description>The latest articles on Forem by Kong (@kong).</description>
    <link>https://forem.com/kong</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Forganization%2Fprofile_image%2F3836%2Fc61fd5fe-3b9f-4105-806b-61ec84c992e6.png</url>
      <title>Forem: Kong</title>
      <link>https://forem.com/kong</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/kong"/>
    <language>en</language>
    <item>
      <title>Installing Kong's API Gateway with Docker</title>
      <dc:creator>Viktor Gamov</dc:creator>
      <pubDate>Fri, 10 Sep 2021 19:57:32 +0000</pubDate>
      <link>https://forem.com/kong/installing-kong-s-api-gateway-with-docker-56gg</link>
      <guid>https://forem.com/kong/installing-kong-s-api-gateway-with-docker-56gg</guid>
      <description>&lt;p&gt;&lt;a href="https://konghq.com/kong"&gt;Kong Gateway&lt;/a&gt; is an API layer for managing APIs and microservices. The easiest way to get started running Kong Gateway is to use Docker.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://youtu.be/sJEID1xEZMg"&gt;In this video&lt;/a&gt;, I'll explain how to run Kong Gateway using Docker and Docker Compose.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://youtu.be/sJEID1xEZMg&amp;lt;br&amp;gt;%0A"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--cY0Il_5U--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2pk7203v19has9r4yk0z.jpg" alt="Installing Kong's API Gateway with Docker"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>8 Common Request Transformation Policies</title>
      <dc:creator>Michael Heap</dc:creator>
      <pubDate>Tue, 27 Jul 2021 13:00:17 +0000</pubDate>
      <link>https://forem.com/kong/8-common-request-transformation-policies-2fp6</link>
      <guid>https://forem.com/kong/8-common-request-transformation-policies-2fp6</guid>
      <description>&lt;p&gt;API gateway request transformation policies are incredibly powerful. There are many situations when an API developer can take advantage of request transformations to adjust the shape and values of a request to cleanly fit their API.&lt;/p&gt;

&lt;p&gt;Let’s say you’re deprecating a certain endpoint for your API, but you still need to support the old specification for a transition period. Request transformations let you accept requests according to the old specification, transform them to fit the new specification and then forward them.&lt;/p&gt;

&lt;p&gt;Or maybe you discovered that incorrect documentation on an endpoint’s query parameter specification has been in the wild for far too long, which is why so many users have been encountering errors. Rather than changing your API to fit bad documentation, you can use request transformations to modify requests as they come in, shaping them according to how your API is supposed to work.&lt;/p&gt;

&lt;p&gt;Or perhaps it’s simply time to implement basic security best practices, like stripping or obfuscating sensitive data in the headers before letting them continue upstream.&lt;/p&gt;

&lt;p&gt;For these and many other reasons, request transformations can be your go-to solution.&lt;/p&gt;

&lt;p&gt;This article will look at how we might use &lt;a href="https://konghq.com/kong/"&gt;Kong Gateway&lt;/a&gt;, coupled with the Request Transformer &lt;a href="https://docs.konghq.com/hub/kong-inc/request-transformer/"&gt;plugin&lt;/a&gt;, to configure, intercept and transform requests as they make their way to an upstream route. Setup and configuration are incredibly simple. We’ll cover several common use cases:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Copying an API Key from the query string to the header&lt;/li&gt;
&lt;li&gt;Removing a query string value&lt;/li&gt;
&lt;li&gt;Moving an API key from a query string to the header&lt;/li&gt;
&lt;li&gt;Adding a version number to a query string&lt;/li&gt;
&lt;li&gt;Modifying the header token to Bearer Auth&lt;/li&gt;
&lt;li&gt;Moving JWT from header to body&lt;/li&gt;
&lt;li&gt;Sanitizing the body&lt;/li&gt;
&lt;li&gt;Changing the HTTP method&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This should give you enough foundation to craft your own transformations, custom-tailored for your application situation.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Overview of Core Concepts&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Before we dive in, let’s quickly cover the technologies we’ll be using for our walkthrough.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Kong Gateway&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Kong Gateway is a thin-layer, front-line “gateway” sitting in front of your system’s upstream services. Whether those upstream services are API servers, web servers or any other cloud microservices, Kong Gateway handles traffic control, authentication, load balancing and more. &lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Request Transformer Plugin&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;The Request Transformer plugin for Kong Gateway comes built in. As requests come through Kong, you can configure the plugin to transform those requests—mutating headers, query string parameters, the request body and so on—before forwarding those requests to their final destination. Transformations are highly configurable and extremely powerful, giving you a lot of control over the precise shape of requests before they hit your endpoint.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Mockbin&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://mockbin.org/"&gt;Mockbin&lt;/a&gt; is an online custom endpoint generator used for testing HTTP requests and tracking responses. Mockbin is exactly what we need for our walkthrough—as we set up transformations, send requests and then inspect the result.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Our Walkthrough Approach&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;To start, we’ll set up our Mockbin endpoint as our “upstream service.” We only need a single endpoint, and we’ll hit it with &lt;code&gt;GET&lt;/code&gt; and &lt;code&gt;POST&lt;/code&gt; requests. Then, we’ll make sure Kong Gateway is installed and configured properly.&lt;/p&gt;

&lt;p&gt;We’ll look at configuring the Request Transformer plugin for each transformation that we want to demonstrate. Then, we’ll send our request (using &lt;code&gt;curl&lt;/code&gt;). Finally, we’ll inspect the request at Mockbin. We want to see what the request looked like when it arrived at Mockbin &lt;em&gt;after&lt;/em&gt; passing through Kong and the Request Transformer plugin.&lt;/p&gt;

&lt;p&gt;Are you ready? Roll out!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Want to set up a request transformation for your API gateway with clicks instead of code?&lt;/strong&gt; &lt;a href="https://konghq.com/kong-konnect/"&gt;&lt;strong&gt;Try Konnect for free &amp;gt;&amp;gt;&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Set Up Mockbin Endpoint&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Mockbin is a simple and easy-to-use test endpoint generator. On the website, click on the &lt;strong&gt;Create Bin&lt;/strong&gt; link to get started.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--hmpZxh_8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://konghq.com/wp-content/uploads/2021/07/mockbin-website.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--hmpZxh_8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://konghq.com/wp-content/uploads/2021/07/mockbin-website.png" alt="mockbin-website"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--zUss9mZJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://konghq.com/wp-content/uploads/2021/07/mockbin-create-bin.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--zUss9mZJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://konghq.com/wp-content/uploads/2021/07/mockbin-create-bin.png" alt="mockbin-create-bin"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And, just like that, your endpoint has been created! From here, you will need your endpoint URL. This is just &lt;a href="https://mockbin.org/bin/%7BBIN-IDENTIFIER%7D"&gt;https://mockbin.org/bin/{BIN-IDENTIFIER}&lt;/a&gt;. But, for good measure, you can right-click on &lt;strong&gt;Visit in Browser&lt;/strong&gt; and copy the link address. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--LELaE-yN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://konghq.com/wp-content/uploads/2021/07/mockbin-get-bin-link.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--LELaE-yN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://konghq.com/wp-content/uploads/2021/07/mockbin-get-bin-link.png" alt="mockbin-get-bin-link"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To test it out, you can open a new tab in your browser and visit the link you just copied. Doing so will send a &lt;code&gt;GET&lt;/code&gt; request to your Mockbin endpoint. To see the details for this request, go back to the browser tab with your Mockbin details and click on &lt;strong&gt;View History&lt;/strong&gt;. You’ll see a running log of requests to this endpoint. You should see the &lt;code&gt;GET&lt;/code&gt; request that you just sent:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--gwAwxUk7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://konghq.com/wp-content/uploads/2021/07/mockbin-history.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--gwAwxUk7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://konghq.com/wp-content/uploads/2021/07/mockbin-history.png" alt="mockbin-history"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Our Mockbin endpoint is up and running and ready to go.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Set Up Kong Gateway&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Spinning up Kong Gateway is quite straightforward. First, you’ll need to &lt;a href="https://konghq.com/install/"&gt;install Kong&lt;/a&gt; on your local machine. There are many different installation options, so you can choose whichever best fits your environment.&lt;/p&gt;

&lt;p&gt;After installing Kong, create a project folder on your local machine. For simplicity, I’m creating a sub-folder called “project” in my home folder. Then, in that folder, run the command to generate a declarative configuration file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;~$ mkdir project
~$ cd project
~/project$ kong config init
~/project$ tree
.
└── kong.yml

0 directories, 1 file
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For our use of the Request Transformer plugin, we can put all of our service and route setup and plugin configurations in a single file. Then, start Kong. Kong does not need to write to a database, and we don’t need to do any further on-the-fly configuration as we go along. This is Kong’s &lt;a href="https://docs.konghq.com/gateway-oss/2.4.x/db-less-and-declarative-config/"&gt;DB-less and Declarative Configuration&lt;/a&gt;, and it’s sufficient for what we need.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;kong.yml&lt;/code&gt; file is a starter template for a declarative configuration file. Let’s open it and modify it to look like the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# ~/project/kong.yml
_format_version: "2.1"

services:
- name: mockbin
  url: https://mockbin.org/bin/REPLACE-WITH-YOUR-BIN-IDENTIFIER
routes:
- name: untouched
  service: mockbin
  paths:
    - /untouched
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let’s briefly go over what we’ve done here. The &lt;code&gt;&lt;br&gt;
_format_version&lt;/code&gt; line, which is required, specifies the version number of the declarative configuration syntax we’re using. Next, we declare an upstream service, and we give it the arbitrary name “mockbin” and specify the URL for this upstream service. Make sure you use your unique URL for the Mockbin endpoint you created earlier.&lt;/p&gt;

&lt;p&gt;Next, we create a route, which we will arbitrarily name “untouched.” This route listens on the Kong Gateway for requests that go to the path &lt;code&gt;/untouched&lt;/code&gt;, and then it forwards those requests to our upstream service called “mockbin.” In this first example, we are not adding a Request Transformer plugin. Requests will proceed through Kong Gateway untouched, continuing to Mockbin.&lt;/p&gt;

&lt;p&gt;We’re almost ready! The last thing we need to do is tell Kong where to look for our declarative configuration file when it starts up. To do this, we need a &lt;code&gt;kong.conf&lt;/code&gt; file, copied from the default template provided to us upon installation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;~/project$ cd /etc/kong
/etc/kong$ cp kong.conf.default kong.conf
~/project$ sudo vi kong.conf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the &lt;code&gt;kong.conf&lt;/code&gt; file, there are two lines that we need to edit. At around line 922, we need to tell Kong that we won’t be using a database. And at around line 1106, we need to provide the absolute path to our declarative configuration file. That’s the &lt;code&gt;kong.conf&lt;/code&gt; file in your project folder.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# PATH: /etc/kong/kong.conf

...

# AROUND LINE 922
# inherited from the corresponding main connection config described above but
# may be optionally overwritten explicitly using the `pg_ro_*` config below.

database = off # Determines which of PostgreSQL or Cassandra
                              # this node will use as its datastore.

# AROUND LINE 1106
                              # This value is only used during
                              # migrations.

declarative_config = /PATH/TO/YOUR/PROJECT/FOLDER/kong.yml
                              # The path to the declarative configuration
                              # file which holds the specification of all
                              # entities (Routes, Services, Consumers, etc.)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With the file saved, we’re ready to start up Kong.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;~/project$ sudo kong start
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now that Kong is running, let’s send a request to &lt;code&gt;localhost:8000&lt;/code&gt;, which is the port where Kong is listening. We’ll send a &lt;code&gt;GET&lt;/code&gt; request to the &lt;code&gt;/untouched&lt;/code&gt; endpoint, and we’ll tack on a query string parameter:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;~/project$ curl -X GET 'http://localhost:8000/untouched?hello=world'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In your browser, refresh the page with your Mockbin endpoint history log. You should see a new entry for a &lt;code&gt;GET&lt;/code&gt; request.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--sDWNiMOM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://konghq.com/wp-content/uploads/2021/07/untouched_GET-01.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--sDWNiMOM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://konghq.com/wp-content/uploads/2021/07/untouched_GET-01.png" alt="untouched_GET-01"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you view the Request Details, you can see that the &lt;code&gt;queryString&lt;/code&gt; array has a pair that matches the parameters we sent to Kong. It looks like Kong successfully forwarded our (untouched) request to Mockbin!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--LdP2tI-I--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://konghq.com/wp-content/uploads/2021/07/untouched_GET-02.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--LdP2tI-I--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://konghq.com/wp-content/uploads/2021/07/untouched_GET-02.png" alt="untouched_GET-02"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Just for good measure, let’s also send a &lt;code&gt;POST&lt;/code&gt; request to the same endpoint at Kong. We’ll set our “Content-Type” header and tack on a request body like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;~/project$ curl -X POST \
           -H 'Content-Type: application/json' \
           -d '{"hello":"world"}' \
           'http://localhost:8000/untouched'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Again, we refresh the Mockbin log, and we see our &lt;code&gt;POST&lt;/code&gt; request. Here, we see our Request Body, which matches what we sent to Kong.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--brDdcHh---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://konghq.com/wp-content/uploads/2021/07/untouched_POST_01.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--brDdcHh---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://konghq.com/wp-content/uploads/2021/07/untouched_POST_01.png" alt="untouched_POST_01"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If we poke around at the Request Details, we also see the “Content-Type” value that we set in our header, along with our &lt;code&gt;POST&lt;/code&gt; body data.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--3x5t2Rbp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://konghq.com/wp-content/uploads/2021/07/unnamed-1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--3x5t2Rbp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://konghq.com/wp-content/uploads/2021/07/unnamed-1.png" alt="untouched_POST_02"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ZKzz-3xx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://konghq.com/wp-content/uploads/2021/07/untouched_POST_03.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ZKzz-3xx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://konghq.com/wp-content/uploads/2021/07/untouched_POST_03.png" alt="untouched_POST_03"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It looks like we have finished our setup. We’ve connected all the pieces. It’s time to start playing around with some common request transformations.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Common Request Transformations&lt;/strong&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;1. Copy API key from query string to header&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Let’s start with a common scenario. Your API users have been adding their API key as a query string parameter, but you’d like to transition them toward attaching it as a custom header value instead. Until you’re certain that all of your API users have gotten the memo that the key should be in the header, you want to accommodate the stragglers. What you need is a request transformation that copies the value from the query string parameter to a new header value.&lt;/p&gt;

&lt;p&gt;Here is how our &lt;code&gt;kong.yml&lt;/code&gt; file would look:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# ~/project/kong.yml
_format_version: "2.1"

services:
- name: mockbin
  url: https://mockbin.org/bin/REPLACE-WITH-YOUR-BIN-IDENTIFIER
routes:
- name: copy-query-to-header
  service: mockbin
  paths:
    - /copy-q2h
plugins:
- name: request-transformer
  route: copy-query-to-header
  config:
    add:
      headers:
        - api-key:$(query_params.api_key)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Similar to our first example, we’ve created a service, along with a route that forwards to this service. For this route, Kong will listen on the path &lt;code&gt;/copy-q2h&lt;/code&gt;. Next, we add a plugin. The name of this plugin ( &lt;strong&gt;not&lt;/strong&gt; arbitrary) is &lt;code&gt;request-transformer&lt;/code&gt;. The plugin is for our specific route.&lt;/p&gt;

&lt;p&gt;What kinds of request transformations should this plugin do? It will add a header. The new key for this header will be &lt;code&gt;api-key&lt;/code&gt;. The value will be copied from the query string parameter called &lt;code&gt;api_key&lt;/code&gt;. This part uses the &lt;a href="https://docs.konghq.com/hub/kong-inc/request-transformer/#template-as-value"&gt;plugin’s templating feature&lt;/a&gt; to grab a value that came in the query string&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Don’t forget: Whenever we modify the kong.yml file, we need to restart Kong.&lt;/strong&gt; Let’s restart Kong and send our request.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;~/project$ sudo kong restart
~/project$ curl -X GET 'http://localhost:8000/copy-q2h?api_key=THISISMYAPIKEY'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We’ve sent a &lt;code&gt;GET&lt;/code&gt; request to our &lt;code&gt;/copy-q2h&lt;/code&gt; endpoint. We tacked on a query string parameter &lt;code&gt;api_key=THISISMYAPIKEY&lt;/code&gt;. Let’s see how this request was transformed by refreshing the Mockbin log.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--rxa-ahnQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://konghq.com/wp-content/uploads/2021/07/copy-q2h-01.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--rxa-ahnQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://konghq.com/wp-content/uploads/2021/07/copy-q2h-01.png" alt="copy-q2h-01"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As we scroll down the Request Details, we see in the headers that there is an &lt;code&gt;api-key&lt;/code&gt; header with the value &lt;code&gt;THISISMYAPIKEY&lt;/code&gt;. It looks like our copy transformation worked.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--wL9kse1Z--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://konghq.com/wp-content/uploads/2021/07/copy-q2h-02.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--wL9kse1Z--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://konghq.com/wp-content/uploads/2021/07/copy-q2h-02.png" alt="copy-q2h-02"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You will notice that the &lt;code&gt;api_key=THISISMYAPIKEY&lt;/code&gt; query string parameter is still in the request, though. That’s okay for now. We’ll deal with that in a little bit.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--AtPbx_WZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://konghq.com/wp-content/uploads/2021/07/copy-q2h-03.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--AtPbx_WZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://konghq.com/wp-content/uploads/2021/07/copy-q2h-03.png" alt="copy-q2h-03"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;2. Remove query string value&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Another common scenario involves the need to remove certain query string parameters completely. Perhaps for privacy reasons or security reasons, sanitizing query parameters is a common use case for request transformations.&lt;/p&gt;

&lt;p&gt;In the following &lt;code&gt;kong.yml&lt;/code&gt; example, we want to remove the key-value pairs for the &lt;code&gt;api_key&lt;/code&gt; and &lt;code&gt;password&lt;/code&gt; query string parameters. Similar to our previous example, we create a route (listening on &lt;code&gt;/strip-q&lt;/code&gt;), and we create a plugin on that route that removes our undesirable parameters:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# ~/project/kong.yml
_format_version: "2.1"

services:
- name: mockbin
  url: https://mockbin.org/bin/REPLACE-WITH-YOUR-BIN-IDENTIFIER
routes:
- name: strip-query
  service: mockbin
  paths:
    - /strip-q
plugins:
- name: request-transformer
  route: strip-query
  config:
    remove:
      querystring:
        - api_key
        - password
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let’s send a request to this path, adding on a few query parameters. We’ll include the ones we want to strip away, along with one that we would like to keep. Don’t forget to restart Kong!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;~/project$ sudo kong restart
~/project$ curl -X GET \
'http://localhost:8000/strip-q?api_key=THISISMYAPIKEY&amp;amp;username=johndoe&amp;amp;password=THISISMYPASSWORD'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Taking a glance at the Mockbin log, we can see that this most recent GET request received the query string parameter we wanted to keep (&lt;code&gt;username=johndoe&lt;/code&gt;) but didn’t receive the undesirable ones. That’s a good sign.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--59HjX3Dt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://konghq.com/wp-content/uploads/2021/07/strip-q-01.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--59HjX3Dt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://konghq.com/wp-content/uploads/2021/07/strip-q-01.png" alt="strip-q-01"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A closer look at the query string array in Request Details shows that the plugin worked as expected, removing the &lt;code&gt;api_key&lt;/code&gt; and &lt;code&gt;password&lt;/code&gt; parameters before forwarding the request to Mockbin.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--3ur_4ilm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://konghq.com/wp-content/uploads/2021/07/Remove-Query-String-Value-Password.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--3ur_4ilm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://konghq.com/wp-content/uploads/2021/07/Remove-Query-String-Value-Password.png" alt="Remove Query String Value Password"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Just a note:&lt;/strong&gt; You could write &lt;code&gt;kong.yml&lt;/code&gt; with multiple routes and multiple plugins. In this article, our file always shows just a single route and a single plugin. That’s just to keep it simple, but you’re not restricted to do it this way.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;3. Move API key from query string to header&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Previously, we copied an API key from the query parameter to a header value, but we left the query parameter in the request. In the following example, let’s do something similar, but we’ll clean up after ourselves by removing the query parameter too. Our configuration for the plugin this time around: 1) adds a header based on the query parameter value, and then 2) removes the query parameter.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# ~/project/kong.yml
_format_version: "2.1"

services:
- name: mockbin
  url: https://mockbin.org/bin/REPLACE-WITH-YOUR-BIN-IDENTIFIER
routes:
- name: move-query-to-header
  service: mockbin
  paths:
    - /move-q2h
plugins:
- name: request-transformer
  route: move-query-to-header
  config:
    add:
      headers:
        - api-key:$(query_params.api_key)
    remove:
      querystring:
        - api_key
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At this point, the keen observer might be asking: “&lt;em&gt;Wait, if you remove the query parameter, how would you copy its value over to the header? Does the configuration order matter, where you have to copy it before you remove it?&lt;/em&gt;” The answer is… no! Kong’s documentation on template values explains it this way:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Note: The plugin creates a non-mutable table of request headers, query strings, and captured URIs before the transformation. Therefore, any update or removal of params used in a template does not affect the rendered value of a template.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Let’s restart Kong and send our request.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;~/project$ sudo kong restart
~/project$ curl -X GET 'http://localhost:8000/move-q2h?api_key=THISISMYAPIKEY'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;An inspection of the Request Details at the Mockbin log shows the value in our headers:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--HRzV02KT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://konghq.com/wp-content/uploads/2021/07/API-Key-Parameters.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--HRzV02KT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://konghq.com/wp-content/uploads/2021/07/API-Key-Parameters.png" alt="API Key Parameters"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;4. Add version number to query string&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Another common case is simply adding a query string parameter to a request. In this example, we’ll add a fixed API version number to all requests that come through our &lt;code&gt;/add-q&lt;/code&gt; route:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# ~/project/kong.yml
_format_version: "2.1"

services:
- name: mockbin
  url: https://mockbin.org/bin/REPLACE-WITH-YOUR-BIN-IDENTIFIER
routes:
- name: add-to-query
  service: mockbin
  paths:
    - /add-q
plugins:
- name: request-transformer
  route: add-to-query
  config:
    add:
      querystring:
        - api_version:2.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We will add the parameter called &lt;code&gt;api_version&lt;/code&gt;, and its value will be &lt;code&gt;2.0&lt;/code&gt;. Let’s restart Kong and send our request.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;~/project$ sudo kong restart
~/project$ curl -X GET 'http://localhost:8000/add-q?username=johndoe'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;While we only set one query parameter (&lt;code&gt;username=johndoe&lt;/code&gt;), we inspect our transformed request at the Mockbin log. There we see in the Request Details that Mockbin received two parameters with the request:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--HfWsTk-R--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://konghq.com/wp-content/uploads/2021/07/add-q-02.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--HfWsTk-R--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://konghq.com/wp-content/uploads/2021/07/add-q-02.png" alt="add-q-02"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It looks like our query parameter add was successful.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;5. Modify header token to Bearer Auth&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Now, let’s experiment with our headers a bit. Imagine the scenario where your API users are attaching their authorization token as a header called &lt;code&gt;token&lt;/code&gt;, but you wrote your API to use the Bearer Auth scheme. The token value should be in a header called &lt;code&gt;Authorization&lt;/code&gt;, following the word “Bearer!” Collin, the junior dev who wrote that erroneous API documentation, will get a poor performance review. In the meantime, you’ll use request transformation to fix Collin’s mess.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# ~/project/kong.yml
_format_version: "2.1"

services:
- name: mockbin
  url: https://mockbin.org/bin/REPLACE-WITH-YOUR-BIN-IDENTIFIER
routes:
- name: modify-header
  service: mockbin
  paths:
    - /token-to-auth
plugins:
- name: request-transformer
  route: modify-header
  config:
    add:
      headers:
        - Authorization:Bearer $(headers["token"])
    remove:
      headers:
        - token
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Our configuration again takes advantage of template values, copying the &lt;code&gt;token&lt;/code&gt; value from the token header and structuring a proper Bearer Auth header value. And, of course, we remove the undesirable &lt;code&gt;token&lt;/code&gt; header after we get what we need.&lt;/p&gt;

&lt;p&gt;We restart Kong and send our request.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;~/project$ sudo kong restart
~/project$ curl -X GET \
-H 'token:thisisanopaquestringthatrepresentsajwt' \
'http://localhost:8000/token-to-auth'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For this request, we sent our token value in the header called &lt;br&gt;
&lt;code&gt;token&lt;/code&gt;. Let’s inspect the Request Details at our Mockbin log:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--BGjBQMeu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://konghq.com/wp-content/uploads/2021/07/token-to-auth-02.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--BGjBQMeu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://konghq.com/wp-content/uploads/2021/07/token-to-auth-02.png" alt="token-to-auth-02"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We see the Bearer Auth scheme in our header now. A further inspection of the details shows that the offending &lt;code&gt;token&lt;/code&gt; header is not present. On a side note, you might notice above that we had configured our plugin to add a header with the name “Authorization” (capitalized), but what shows up in Mockbin is “authorized” (lowercase). It looks like this might be an issue with Mockbin—which lowercases all of its header names—and not an issue with the Request Transformer plugin (which addressed this specific issue in a &lt;a href="https://github.com/Kong/kong-plugin-request-transformer/pull/34"&gt;pull request&lt;/a&gt;).&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;strong&gt;6. Move JWT from header (Bearer Auth) to body&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Let’s do some request transformations that modify the request body. In this example, we’ll take the token in Bearer Auth format, and we’ll write it to our request JSON body as a value. While some upstream services look in the header for an authorization token, others might look to the request body. Request transformations provide flexibility, especially when modifying upstream services isn’t an option.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# ~/project/kong.yml
_format_version: "2.1"

services:
- name: mockbin
  url: https://mockbin.org/bin/REPLACE-WITH-YOUR-BIN-IDENTIFIER
routes:
- name: jwt-to-body
  service: mockbin
  paths:
    - /jwt2b
plugins:
- name: request-transformer
  route: jwt-to-body
  config:
    add:
      body:
        - jwt:$(headers["Authorization"]:gsub("^Bearer ",""))
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The syntax for the above plugin configuration is a bit more complicated, but you can probably discern what’s happening. We want to add a key-value pair to our request body. The key is &lt;code&gt;jwt&lt;/code&gt;, and the value will be taken with the &lt;code&gt;Authorization&lt;/code&gt; header but with the initial “Bearer” (plus space) removed.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://docs.konghq.com/hub/kong-inc/request-transformer/#advanced-templates"&gt;plugin documentation&lt;/a&gt; notes that the placeholder is evaluated as Lua expression. So, if you know &lt;a href="https://www.lua.org/manual/5.4/"&gt;Lua&lt;/a&gt;, you can probably do some pretty powerful transformations.&lt;/p&gt;

&lt;p&gt;Let’s restart Kong and send our &lt;code&gt;POST&lt;/code&gt; request, along with headers and body data:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;~/project$ sudo kong restart
~/project$ curl -X POST \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer thisisanopaquestringthatrepresentsajwt' \
-d '{"username":"johndoe" }' \
'http://localhost:8000/jwt2b'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When we look at our Mockbin log for this request, we immediately see the Request Body. It contains the original body we sent (&lt;code&gt;"username":"johndoe"&lt;/code&gt;), but it also contains &lt;br&gt;
&lt;code&gt;jwt&lt;/code&gt;, with the token value that was in our Bearer Auth header.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--lCTKtQ0r--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://konghq.com/wp-content/uploads/2021/07/jwt-to-body-01.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--lCTKtQ0r--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://konghq.com/wp-content/uploads/2021/07/jwt-to-body-01.png" alt="jwt-to-body-01"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You might notice, from our plugin configuration, that we decided to leave our Bearer Auth header in the request:&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;strong&gt;7. Sanitize body&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Perhaps for sensitive data that might come through the request body, you will need a request transformation that sanitizes it but doesn’t remove it. This helps your upstream service know that the data &lt;em&gt;did&lt;/em&gt; come through, but it’s just no longer available. For this type of transformation, your configuration might look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# ~/project/kong.yml
_format_version: "2.1"

services:
- name: mockbin
  url: https://mockbin.org/bin/REPLACE-WITH-YOUR-BIN-IDENTIFIER
routes:
- name: sanitize-body
  service: mockbin
  paths:
    - /san-b
plugins:
- name: request-transformer
  route: sanitize-body
  config:
    replace:
      body:
      - last4: ****
      - api_key: ********
      - password: ********
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this request transformation, we’re looking in our JSON body for &lt;code&gt;last4&lt;/code&gt;, &lt;code&gt;api_key&lt;/code&gt; or &lt;code&gt;password&lt;/code&gt;. For any of those keys, we want to replace the provided value with a redacted one. After restarting Kong, we send our request:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;~/project$ sudo kong restart
~/project$ curl -X POST \
-H 'Content-Type: application/json' \
-d '{"api_key":"THISISMYAPIKEY", "username":"johndoe", "password":"THISISMYPASSWORD", "last4":9876}' \
'http://localhost:8000/san-b'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A quick glance at the Mockbin log shows our transformed Request Body. Recall that Kong transformed this body &lt;em&gt;before&lt;/em&gt; it was sent to the upstream service, so we can be sure that none of this sensitive data got past our gateway.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;8. Change HTTP method&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;For our final example, let’s demonstrate a request method transformation. Let’s assume that &lt;code&gt;PUT&lt;/code&gt; requests to a given route need to be converted to &lt;code&gt;POST&lt;/code&gt; requests, and instead, we’d add an &lt;code&gt;"action":"PUT"&lt;/code&gt; key-value pair into the JSON request body.&lt;/p&gt;

&lt;p&gt;In this configuration, we configure our route only to listen for &lt;code&gt;PUT&lt;/code&gt; requests. Then, we configure the plugin to transform the &lt;code&gt;http_method&lt;/code&gt; to &lt;code&gt;POST&lt;/code&gt;. Lastly, we add a key-value pair to our body.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# ~/project/kong.yml
_format_version: "2.1"

services:
- name: mockbin
  url: https://mockbin.org/bin/REPLACE-WITH-YOUR-BIN-IDENTIFIER
routes:
- name: put-to-post
  service: mockbin
  methods:
    - PUT
  paths:
    - /put-to-post
plugins:
- name: request-transformer
  route: put-to-post
  config:
    http_method: POST
    add:
      body:
      - action:PUT
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Restart Kong and send the &lt;code&gt;PUT&lt;/code&gt; request.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;~/project$ sudo kong restart
~/project$ curl -X PUT \
-H 'Content-Type: application/json' \
-d '{"username":"johndoe" }' \
'http://localhost:8000/put-to-post'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We see the successful result in our Mockbin log. The most recent request was a &lt;code&gt;POST&lt;/code&gt; (not &lt;code&gt;PUT&lt;/code&gt;) request. And, we see the &lt;code&gt;action&lt;/code&gt; key-value pair added to our Request Body.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--XW7TTs4D--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://konghq.com/wp-content/uploads/2021/07/unnamed-3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--XW7TTs4D--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://konghq.com/wp-content/uploads/2021/07/unnamed-3.png" alt="Successful Request Transformation Mockbin"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Conclusion&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;We’ve covered a lot of examples in this walkthrough. We’ve transformed query string parameters, headers, bodies and even request methods. The Request Transformer plugin offers several ways to transform parts of the request. While we’ve covered many of them, combining multiple transformations can yield powerful results that uniquely shape a request to fit your API.&lt;/p&gt;

&lt;p&gt;We didn’t cover URI transformations, which allow you to transform the upstream request URI based on the incoming request. You can imagine taking a long REST-compliant URI, chock-full of a chain of resources, ids, sub-resources and more ids. Using URI capturing and template values, the Request Transformer plugin can capture all of that data in the URI and write it into the request body instead, sending the request upstream to a general all-purpose endpoint.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Ready for Advanced Request Transformations?&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;The Kong Konnect enterprise-level &lt;a href="https://docs.konghq.com/hub/kong-inc/request-transformer-advanced/"&gt;Request Transformer Advanced plugin&lt;/a&gt; provides even more targeted transformations with regular expression matching, variables and substitutions.&lt;/p&gt;

&lt;p&gt;All in all, the ability to transform your requests at the gateway level &lt;em&gt;before&lt;/em&gt; they hit your upstream service is critical. Whether it’s because of deprecated specs, documentation-reality misalignment or data privacy and security concerns, having the flexibility to shape incoming requests—and to do so quickly and simply—might be exactly what your DevOps team needs to save the day in a pinch.&lt;/p&gt;

&lt;p&gt;Once you’ve successfully set up API gateway request transformation policies, you may find these other tutorials helpful:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://konghq.com/blog/jwt-kong-gateway"&gt;How to Use the Kong Gateway JWT Plugin for Service Authentication&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://konghq.com/blog/kong-gateway-oauth2/"&gt;4 Steps to Authorizing Services With the Kong Gateway OAuth2 Plugin&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://konghq.com/blog/getting-started-kuma-service-mesh/"&gt;Getting Started With Kuma Service Mesh&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://dev.to/kong-konnect"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Lrm3tu22--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://konghq.com/wp-content/themes/konghq/assets/img/cta-shortcode/konnect.jpg" alt="Get Started with Kong Konnect - The only full stack connectivity platform for cloud native architectures"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The post &lt;a href="https://konghq.com/blog/api-gateway-request-transformation/"&gt;8 Common API Gateway Request Transformation Policies&lt;/a&gt; appeared first on &lt;a href="https://konghq.com"&gt;KongHQ&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>tutorial</category>
      <category>apigateway</category>
      <category>konggateway</category>
      <category>kongplugins</category>
    </item>
    <item>
      <title>20 Lines of JavaScript to Create a Kong Gateway Plugin</title>
      <dc:creator>Michael Heap</dc:creator>
      <pubDate>Wed, 26 May 2021 13:00:48 +0000</pubDate>
      <link>https://forem.com/kong/building-a-kong-gateway-plugin-with-just-20-lines-of-javascript-449f</link>
      <guid>https://forem.com/kong/building-a-kong-gateway-plugin-with-just-20-lines-of-javascript-449f</guid>
      <description>&lt;p&gt;We recently sat down to discuss the language for the next &lt;a href="https://konghq.com/kong/"&gt;Kong Gateway&lt;/a&gt; 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 &lt;a href="https://konghq.com/blog/kong-gateway-oss-2-4-released/"&gt;Kong Gateway (OSS) 2.4 release&lt;/a&gt;, that functionality is now available to you all!&lt;/p&gt;

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

&lt;h2&gt;
  
  
  Bootstrapping Your Development Environment
&lt;/h2&gt;

&lt;p&gt;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 &lt;code&gt;msgpack&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;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 &lt;code&gt;docker&lt;/code&gt;-based environment for you to use.&lt;/p&gt;

&lt;p&gt;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:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ git clone https://github.com/Kong/docker-kong-js-pdk
$ cd kong-js-pdk-dev
$ docker-compose build
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Creating Your First Plugin
&lt;/h2&gt;

&lt;p&gt;The configuration provided in the environment we created reads all plugins from the &lt;code&gt;plugins&lt;/code&gt; directory. It’s currently empty as we have not created our first plugin yet.&lt;/p&gt;

&lt;p&gt;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 &lt;code&gt;clacks.js&lt;/code&gt; in the &lt;code&gt;plugins&lt;/code&gt; directory with the following contents:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class ClacksPlugin {
  async access(kong) {
    await kong.response.setHeader(`X-Clacks-Overhead`, "GNU Terry Pratchett");
  }
}

module.exports = {
  Plugin: ClacksPlugin,
  Version: "0.1.0"
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;There are five phases available for HTTP requests in the life-cycle of a Kong Gateway request:&lt;/p&gt;

&lt;p&gt;-&lt;code&gt;certificate&lt;/code&gt; – Executed once per request when the connection is SSL/TLS enabled&lt;br&gt;
-&lt;code&gt;rewrite&lt;/code&gt; – Performed before the API gateway does any routing&lt;br&gt;
-&lt;code&gt;access&lt;/code&gt; – 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&lt;br&gt;
-&lt;code&gt;response&lt;/code&gt; – Allows you to manipulate the response from the upstream. Implementing this phase has a performance penalty as it enables request buffering&lt;br&gt;
-&lt;code&gt;log&lt;/code&gt; – Executed after the request has been completed&lt;/p&gt;
&lt;h2&gt;
  
  
  Enable the Plugin
&lt;/h2&gt;

&lt;p&gt;The environment we’re running uses Kong’s &lt;a href="https://docs.konghq.com/gateway-oss/2.4.x/db-less-and-declarative-config/#what-is-declarative-configuration"&gt;declarative config&lt;/a&gt; capability. That means that we need to update the config file to enable our new plugin. Open up &lt;code&gt;config/kong.yml&lt;/code&gt;, and you should see a service defined that proxies to mockbin.org:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;services:
  - name: example-service
    url: https://mockbin.org
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As our file name was &lt;code&gt;clacks.js&lt;/code&gt;, our plugin will be called &lt;code&gt;clacks&lt;/code&gt;. Let’s enable the plugin in the definition now:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;services:
  - name: example-service
    url: https://mockbin.org
    plugins:
      - name: clacks
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;KONG_PLUGINS: bundled,clacks
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Making a Request
&lt;/h2&gt;

&lt;p&gt;At this point the &lt;a href="https://konghq.com/learning-center/api-gateway/"&gt;API gateway&lt;/a&gt; is ready to run our new plugin, so let’s go ahead and start it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ docker-compose up
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;docker-compose.yml&lt;/code&gt; file forwards the API gateway port to our local machine. That means we can make requests to &lt;code&gt;localhost:8000&lt;/code&gt; to test our service.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ 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...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I can see the &lt;code&gt;X-Clacks-Overhead&lt;/code&gt; header in the response, which means that our plugin works as intended!&lt;/p&gt;

&lt;h2&gt;
  
  
  Making It Configurable
&lt;/h2&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;There is an ongoing discussion based on &lt;a href="https://tools.ietf.org/html/rfc6648"&gt;RFC 6648&lt;/a&gt; about if custom headers need an &lt;code&gt;X-&lt;/code&gt; prefix. Let’s make our plugin configurable so that people can decide if they want to use the &lt;code&gt;X-&lt;/code&gt; prefix.&lt;/p&gt;

&lt;p&gt;Plugin configuration is controlled using the &lt;code&gt;Schema property&lt;/code&gt; in &lt;code&gt;module.exports&lt;/code&gt; at the end of &lt;code&gt;clacks.js&lt;/code&gt;. Let’s add an entry to define a &lt;code&gt;use_prefix&lt;/code&gt; option that’s a boolean with a default value of &lt;code&gt;true&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;module.exports = {
  Plugin: ClacksPlugin,
  Schema: [{ use_prefix: { type: "boolean", default: true } }],
  Version: "0.1.0"
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;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"
    );
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;services:
  - name: example-service
    url: https://mockbin.org
    plugins:
      - name: clacks
        config:
          use_prefix: false
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ 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...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Just 20 lines of Javascript, and we have a working Kong Gateway plugin, complete with configuration options!&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;If you’re looking for more plugin examples, take a look at some demo plugins:&lt;/strong&gt;&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;If you have any questions, post them on&lt;/strong&gt; &lt;a href="https://discuss.konghq.com/"&gt;&lt;strong&gt;Kong Nation&lt;/strong&gt;&lt;/a&gt; &lt;strong&gt;.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;To stay in touch, join the &lt;a href="https://konghq.com/community/"&gt;Kong Community&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Once you’ve successfully set up a custom Kong plugin with JavaScript, you may find these other tutorials helpful:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://konghq.com/blog/jwt-kong-gateway"&gt;How to Use the Kong Gateway JWT Plugin for Service Authentication&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://konghq.com/blog/kong-gateway-oauth2/"&gt;4 Steps to Authorizing Services With the Kong Gateway OAuth2 Plugin&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://konghq.com/blog/getting-started-kuma-service-mesh/"&gt;Getting Started With Kuma Service Mesh&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://docs.konghq.com/hub/"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--OEBfUbR8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://konghq.com/wp-content/themes/konghq/assets/img/cta-shortcode/kong-hub.jpg" alt="Visit Kong Hub - Extend Kong with 100+ powerful plugins, modules, and integrations"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The post &lt;a href="https://konghq.com/blog/kong-gateway-plugin-javascript/"&gt;Building a Kong Gateway Plugin with JavaScript&lt;/a&gt; appeared first on &lt;a href="https://konghq.com"&gt;KongHQ&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>apigateway</category>
      <category>javascript</category>
      <category>plugins</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Protecting Services With API Gateway Rate Limiting</title>
      <dc:creator>Julia Salem</dc:creator>
      <pubDate>Tue, 18 May 2021 13:00:19 +0000</pubDate>
      <link>https://forem.com/kong/protecting-services-with-api-gateway-rate-limiting-413</link>
      <guid>https://forem.com/kong/protecting-services-with-api-gateway-rate-limiting-413</guid>
      <description>&lt;p&gt;The Kong Gateway Rate Limiting &lt;a href="https://docs.konghq.com/hub/kong-inc/rate-limiting/"&gt;plugin&lt;/a&gt; is one of our most popular traffic control add-ons. You can configure the plugin with a policy for what constitutes “similar requests” (requests coming from the same IP address, for example), and you can set your limits (limit to 10 requests per minute, for example). This tutorial will walk through how simple it is to enable rate limiting in your &lt;a href="https://konghq.com/kong/"&gt;Kong Gateway&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Rate Limiting: Protecting Your Server 101
&lt;/h2&gt;

&lt;p&gt;Let’s take a step back and go over the concept of rate limiting for those who aren’t familiar.&lt;/p&gt;

&lt;p&gt;Rate limiting is remarkably effective and ridiculously simple. It’s also regularly forgotten. Rate limiting is a defensive measure you can use to prevent your server or application from being paralyzed. By restricting the number of similar requests that can hit your server within a window of time, you ensure your server won’t be overwhelmed and debilitated.&lt;/p&gt;

&lt;p&gt;You’re not only guarding against malicious requests. Yes, you want to shut down a bot that’s trying to discover login credentials with a brute force attack. You want to stop scrapers from slurping up your content. You want to safeguard your server from DDOS attacks.&lt;/p&gt;

&lt;p&gt;But it’s also vital to limit non-malicious requests. Sometimes, it’s somebody else’s buggy code that hits your API endpoint 10 times a second rather than one time every 10 minutes. Or, perhaps only your premium users get unlimited API requests, while your free-tier users only get a hundred requests an hour.&lt;/p&gt;

&lt;h2&gt;
  
  
  Mini-Project for Kong Gateway Rate Limiting
&lt;/h2&gt;

&lt;p&gt;In our mini-project for this article, we’re going to walk through a basic use case: Kong Gateway with the Rate Limiting plugin protecting a simple API server. Here are our steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create Node.js Express API server with a single “hello world” endpoint.&lt;/li&gt;
&lt;li&gt;Install and set up Kong Gateway.&lt;/li&gt;
&lt;li&gt;Configure Kong Gateway to sit in front of our API server.&lt;/li&gt;
&lt;li&gt;Add and configure the Rate Limiting plugin.&lt;/li&gt;
&lt;li&gt;Test our rate limiting policies.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;After walking through these steps together, you’ll have what you need to tailor the Rate Limiting plugin for your unique business needs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Want to set up rate limiting for your API gateway with clicks instead of code? &lt;a href="https://konghq.com/kong-konnect/"&gt;Try Konnect for free &amp;gt;&amp;gt;&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Create a Node.js Express API Server
&lt;/h2&gt;

&lt;p&gt;To get started, we’ll create a simple API server with a single endpoint that listens for a &lt;code&gt;GET&lt;/code&gt; request and responds with “hello world.” At the command line, create a project folder and initialize a Node.js application:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;~/$ mkdir project
~/$ cd project
~/project$ yarn init
// Accept all defaults
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, we’ll add Express, which is the only package we’ll need:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;~/project$ yarn add express
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Lastly, let’s create a simple server with our “hello world” endpoint. In your project folder, create an index.js file with these contents:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/* PATH: ~/project/index.js
*/
const express = require('express')
const server = express()
const port = 3000
server.get('/', (req, res) =&amp;gt; {
 console.log(req.headers)
 res.status(200).send('Hello world!')
})
server.listen(port, () =&amp;gt; {
 console.log(`Server is listening on http://localhost:${port}`)
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, spin up your server:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;~/project$ node index.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In your browser, you can visit &lt;a href="http://localhost:3000"&gt;http://localhost:3000&lt;/a&gt;. Here’s what you should see:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--VqB4mL8I--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://konghq.com/wp-content/uploads/2021/05/local-host-hello-world.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--VqB4mL8I--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://konghq.com/wp-content/uploads/2021/05/local-host-hello-world.png" alt="local host hello world"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let’s also use &lt;a href="https://insomnia.rest/"&gt;Insomnia&lt;/a&gt;, a desktop client for API testing. In Insomnia, we send a &lt;code&gt;GET&lt;/code&gt; request to &lt;a href="http://localhost:3000"&gt;http://localhost:3000&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--wvvUIsX1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://konghq.com/wp-content/uploads/2021/05/local-host-hello-world-insomnia.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--wvvUIsX1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://konghq.com/wp-content/uploads/2021/05/local-host-hello-world-insomnia.png" alt="local host hello world in Insomnia"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Our Node.js API server with its single endpoint is up and running. We have our &lt;code&gt;200 OK&lt;/code&gt; response.&lt;/p&gt;

&lt;p&gt;Keep that terminal window with the node running. We’ll do the rest of our work in a separate terminal window.&lt;/p&gt;

&lt;h2&gt;
  
  
  Install and Set Up Kong Gateway
&lt;/h2&gt;

&lt;p&gt;Next, we’ll &lt;a href="https://konghq.com/install/"&gt;install Kong Gateway&lt;/a&gt; to sit in front of our API server. These steps will vary depending on your local environment.&lt;/p&gt;

&lt;p&gt;Simple usage of the Rate Limiting plugin supports configuring Kong in DB-less mode with a declarative configuration. That means, instead of sending configurations to Kong Gateway one step at a time, with those configurations stored in a database, we can use a single declarative &lt;code&gt;.yml&lt;/code&gt; file for specifying our entire Kong configuration.&lt;/p&gt;

&lt;p&gt;After installing Kong, we generate a starter .yml file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;~/project$ kong config init
~/project$ tree -L 1
.
├── index.js
├── kong.yml
├── node_modules
├── package.json
└── yarn.lock
1 directory, 4 files
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We’ll come back to that kong.yml file in a moment.&lt;/p&gt;

&lt;p&gt;Now, let’s tell Kong where to look for that declarative configuration file upon startup. In /etc/kong, there is a &lt;br&gt;
&lt;code&gt;kong.conf.default&lt;/code&gt; file that we’ll need to copy as &lt;code&gt;kong.conf&lt;/code&gt; and then edit:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;~/project$ cd /etc/kong
/etc/kong$ sudo su
root:/etc/kong$ cp kong.conf.default kong.conf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, we edit the &lt;code&gt;kong.conf&lt;/code&gt; file. You’ll likely need root privileges to do this. There are two edits that we need to make:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# PATH: /etc/kong/kong.conf

# line ~839: Uncomment this line and set to off
database = off

# line ~1023, Uncomment this line. Set to absolute path to kong.yml
declarative_config = /PATH/TO/YOUR/project/kong.yml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Configure Kong Gateway With Our Service and Routes
&lt;/h2&gt;

&lt;p&gt;Before we start up Kong, let’s edit the declarative configuration file generated in our project folder. It should look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# PATH: ~/project/kong.yml

_format_version: "2.1"

services:
- name: my-api-server
  url: http://localhost:3000/
  routes:
  - name: api-routes
    paths:
    - /api
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let’s walk through what this configuration does. After setting the syntax version (2.1), we configure a new upstream service for which Kong will serve as an API gateway. Our service, which we name my-api-server, listens for requests at the URL &lt;a href="http://localhost:3000"&gt;http://localhost:3000&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;We associate a route (arbitrarily named &lt;br&gt;
&lt;code&gt;api-routes&lt;/code&gt;) for our service with the path &lt;code&gt;/api&lt;/code&gt;. Kong Gateway will listen for requests to &lt;code&gt;/api&lt;/code&gt;, and then route those requests to our API server at &lt;a href="http://localhost:3000"&gt;http://localhost:3000&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;With our declarative configuration file in place, we start Kong:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;~/project$ sudo kong start
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, in Insomnia, we send a &lt;code&gt;GET&lt;/code&gt; request through Kong Gateway, which listens at &lt;a href="http://localhost:8000"&gt;http://localhost:8000&lt;/a&gt;, to the &lt;code&gt;/api&lt;/code&gt; path:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Ovx9Qnh---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://konghq.com/wp-content/uploads/2021/05/insomnia-get-request.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Ovx9Qnh---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://konghq.com/wp-content/uploads/2021/05/insomnia-get-request.png" alt="Insomnia get request"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Note that, by sending our request to port &lt;code&gt;8000&lt;/code&gt;, we are going &lt;em&gt;through&lt;/em&gt; Kong Gateway to get to our API server.&lt;/p&gt;

&lt;h2&gt;
  
  
  Add the Kong Gateway Rate Limiting Plugin
&lt;/h2&gt;

&lt;p&gt;Now that we have Kong Gateway sitting in front of our API server, we’ll add in the Rate Limiting Plugin and test it out. We will need to add a few lines to our &lt;code&gt;kong.yml&lt;/code&gt; declarative configuration file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# PATH: ~/project/kong.yml

_format_version: "2.1"

services:
- name: my-api-server
  url: http://localhost:3000/
  routes:
  - name: api-routes
    paths:
    - /api
  plugins:
  - name: rate-limiting
    config:
      minute: 5
      hour: 12
      policy: local
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We’ve added the entire plugins section underneath our my-api-server service. We specify the name of the plugin, &lt;code&gt;rate-limiting&lt;/code&gt;. This name is &lt;em&gt;not&lt;/em&gt; arbitrary but refers to the actual &lt;code&gt;rate-limiting&lt;/code&gt; plugin in the Kong package.&lt;/p&gt;

&lt;p&gt;In this first run, we’ve configured the plugin with &lt;code&gt;minute: 5&lt;/code&gt;, which allows for up to five requests per minute. We’ve also added hour &lt;code&gt;: 12&lt;/code&gt;, which limits the requests per hour to 12. We’re using the local policy, which has to do with how Kong will store and increment request counts. We’ll talk about this policy configuration more below.&lt;/p&gt;

&lt;p&gt;Let’s restart Kong:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;~/project$ sudo kong restart
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, back in Insomnia, we test out sending some requests to our API endpoint. If you send a request every few seconds, you’ll see that the first five requests received a &lt;code&gt;200 OK&lt;/code&gt; response. However, if you exceed five requests within a minute:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--lSvpme0r--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://konghq.com/wp-content/uploads/2021/05/insomnia-test-kong-rate-limiting.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--lSvpme0r--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://konghq.com/wp-content/uploads/2021/05/insomnia-test-kong-rate-limiting.png" alt="Insomnia test Kong's rate limiting plugin"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The Rate Limiting plugin detects that requests have exceeded the five-per-minute rule. It doesn’t let the subsequent request through to the API server. Instead, we get a &lt;code&gt;429 Too Many Requests&lt;/code&gt; response.&lt;/p&gt;

&lt;p&gt;Our plugin works!&lt;/p&gt;

&lt;p&gt;If you wait a minute and then try your requests again, you’ll see that you can get another five successful requests until Kong blocks you again with another &lt;code&gt;429&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;At this point, we’ve sent 10 requests over several minutes. But you’ll recall that we configured our plugin with &lt;code&gt;hour: 12&lt;/code&gt;. That means our 11th and 12th requests will be successful. However, the system will reject our 13th request  even though we haven’t exceeded the five-per-minute rule . That’s because we’ll have exceeded the 12-per-hour rule.&lt;/p&gt;

&lt;p&gt;The Rate Limiting plugin allows you to limit the number of requests per second, minute, hour, day, month and year.&lt;/p&gt;

&lt;h3&gt;
  
  
  Rate Limiting “Similar” Requests
&lt;/h3&gt;

&lt;p&gt;We’ve configured Kong to count (and limit) requests to our server in our simple use case so far. More likely, we’ll want to apply our rate limits to &lt;em&gt;similar&lt;/em&gt; requests. By “similar,” we might mean “coming from the same IP address” or “using the same API key.”&lt;/p&gt;

&lt;p&gt;For example, let’s say that all users of our API server need to send requests with a unique API key set in headers as x-api-key. We can configure Kong to apply its rate limits on a per-API-key basis as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# PATH: ~/project/kong.yml

_format_version: "2.1"

services:
- name: my-api-server
  url: http://localhost:3000/
  routes:
  - name: api-routes
    paths:
    - /api
  plugins:
  - name: rate-limiting
    config:
      minute: 5
      hour: 12
      policy: local
      limit_by: header
      header_name: x-api-key
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Rate Limiting plugin will apply its limits by grouping requests according to a value found in the &lt;code&gt;x-api-key&lt;/code&gt; in the header. Requests with the same &lt;code&gt;x-api-key&lt;/code&gt; will be considered “similar” requests.&lt;/p&gt;

&lt;p&gt;Let’s restart Kong and see this in action:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;~/project$ sudo kong restart
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Back in Insomnia, we’ll adjust our &lt;code&gt;GET&lt;/code&gt; request slightly by adding a new &lt;code&gt;x-api-key&lt;/code&gt; header value. Let’s first set the value to user1. We send the request multiple times. Our first five requests return a &lt;code&gt;200 OK&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--zsBE2YAp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://konghq.com/wp-content/uploads/2021/05/x-api-key-header-insomnia.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--zsBE2YAp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://konghq.com/wp-content/uploads/2021/05/x-api-key-header-insomnia.png" alt="x-api-key header in Insomnia to test rate limiting"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When we exceed the five-per-minute rule, however, this is what we see:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--LoKOY5o5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://konghq.com/wp-content/uploads/2021/05/Insomnia-api-rate-limit-exceeded.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--LoKOY5o5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://konghq.com/wp-content/uploads/2021/05/Insomnia-api-rate-limit-exceeded.png" alt="Insomnia API Rate Limit Exceeded"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If we change the &lt;code&gt;x-api-key&lt;/code&gt; to a different value (for example, user2), we immediately get &lt;code&gt;200 OK&lt;/code&gt; responses:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--oRUC78Cp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://konghq.com/wp-content/uploads/2021/05/insomnia-test-kong-rate-limiting-2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--oRUC78Cp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://konghq.com/wp-content/uploads/2021/05/insomnia-test-kong-rate-limiting-2.png" alt="Insomnia test Kong rate limiting"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Requests from &lt;code&gt;user2&lt;/code&gt; are counted separately from requests from &lt;code&gt;user1&lt;/code&gt;. Each unique &lt;code&gt;x-api-key&lt;/code&gt; value gets (according to our rate limiting rules) up to five requests per minute and up to 12 requests per hour.&lt;/p&gt;

&lt;p&gt;You can configure the plugin to &lt;code&gt;limit_by&lt;/code&gt; IP address, a header value, request path or even credentials (like &lt;a href="https://konghq.com/blog/kong-gateway-oauth2/"&gt;OAuth2&lt;/a&gt; or &lt;a href="https://konghq.com/blog/jwt-kong-gateway"&gt;JWT&lt;/a&gt;).&lt;/p&gt;

&lt;h3&gt;
  
  
  Counter Storage “Policy”
&lt;/h3&gt;

&lt;p&gt;In our example above, we set the &lt;code&gt;policy&lt;/code&gt; of the Rate Limiting plugin to &lt;code&gt;local&lt;/code&gt;. This policy configuration controls &lt;a href="https://docs.konghq.com/hub/kong-inc/rate-limiting/#implementation-considerations"&gt;how Kong will store request counters&lt;/a&gt; to apply its rate limits. The &lt;code&gt;local&lt;/code&gt; policy stores in-memory counters. It’s the simplest strategy to implement (there’s nothing else you need to do!). &lt;/p&gt;

&lt;p&gt;However, request counters with this strategy are only &lt;em&gt;mostly&lt;/em&gt; accurate. If you want basic protection for your server, and it’s acceptable if you miscount a request here and there, then the local policy is sufficient. &lt;/p&gt;

&lt;p&gt;The documentation for the Rate Limiting plugin instructs those with needs where “every transaction counts” to use the &lt;code&gt;cluster&lt;/code&gt; (writes to the database) or &lt;code&gt;redis&lt;/code&gt; (writes to Redis key-value store) policy instead.&lt;/p&gt;

&lt;h2&gt;
  
  
  Advanced Rate Limiting
&lt;/h2&gt;

&lt;p&gt;For many common business cases, the open source Rate Limiting plugin has enough configuration options to meet your needs. For those with more complex needs (multiple limits or time windows, integration with Redis Sentinel), Kong also offers their &lt;a href="https://docs.konghq.com/hub/kong-inc/rate-limiting-advanced/"&gt;Rate Limiting Advanced plugin&lt;/a&gt; for &lt;a href="https://konghq.com/kong-konnect/"&gt;Kong Konnect&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Let’s briefly recap what we did in our mini-project. We spun up a simple API server. Then, we installed and configured Kong Gateway to sit in front of our API server. Next, we added the Rate Limiting plugin to count and limit requests to our server, showing how Kong blocks requests once we exceed certain limits within a window of time. &lt;/p&gt;

&lt;p&gt;Lastly, we demonstrated how to group (and count) requests as “similar” with the example of a header value. Doing so enabled our plugin to differentiate counts for requests coming from two different users so that you can apply that rate limit to each user separately.&lt;/p&gt;

&lt;p&gt;That’s all there is to it. Kong’s Rate Limiting plugin makes protecting your server ridiculously simple. As a basic traffic control defense measure, rate limiting can bring incredible power and peace of mind. You can find more details in the &lt;a href="https://docs.konghq.com/hub/kong-inc/rate-limiting/"&gt;rate limiting plugin doc&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you have any additional questions, post them on &lt;a href="https://discuss.konghq.com/"&gt;Kong Nation&lt;/a&gt;. To stay in touch, join the &lt;a href="https://konghq.com/community/"&gt;Kong Community&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Now that you’re successfully protecting services with the Kong Gateway Rate Limiting plugin, you may find these other tutorials helpful:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://konghq.com/blog/custom-lua-plugin-kong-gateway"&gt;Creating Your First Custom Lua Plugin for Kong Gateway&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://konghq.com/blog/openid-connect-api-gateway"&gt;Getting Started With Kong’s OpenID Connect Plugin&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://konghq.com/blog/kong-gateway-oauth2/"&gt;4 Steps to Authorizing Services With the Kong Gateway OAuth2 Plugin&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://konghq.com/blog/jwt-kong-gateway"&gt;How to Use the Kong Gateway JWT Plugin for Service Authentication&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://dev.to/kong-konnect"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Lrm3tu22--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://konghq.com/wp-content/themes/konghq/assets/img/cta-shortcode/konnect.jpg" alt="Get Started with Kong Konnect - The only full stack connectivity platform for cloud native architectures"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The post &lt;a href="https://konghq.com/blog/kong-gateway-rate-limiting/"&gt;Protecting Services With Kong Gateway Rate Limiting&lt;/a&gt; appeared first on &lt;a href="https://konghq.com"&gt;KongHQ&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>apigateway</category>
      <category>tutorial</category>
      <category>opensource</category>
      <category>ratelimiting</category>
    </item>
    <item>
      <title>Using Kubernetes Ingress Controller as an API Gateway</title>
      <dc:creator>Viktor Gamov</dc:creator>
      <pubDate>Tue, 23 Mar 2021 14:18:22 +0000</pubDate>
      <link>https://forem.com/kong/using-kubernetes-ingress-controller-as-an-api-gateway-1lmh</link>
      <guid>https://forem.com/kong/using-kubernetes-ingress-controller-as-an-api-gateway-1lmh</guid>
      <description>&lt;p&gt;&lt;em&gt;In this first section, I’ll provide a quick overview of the business case and the tools you can use to create a Kubernetes ingress API gateway. If you’re already familiar, you could skip ahead to the tutorial section.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Digital transformation has led to a high velocity of data moving through APIs to applications and devices. Companies with legacy infrastructures are experiencing inconsistencies, failures and increased costs. And most importantly, dissatisfied customers.&lt;/p&gt;

&lt;p&gt;All this has led to significant restructuring and modernization, especially within IT. A primary strategy is to embrace Kubernetes and decouple monolithic systems. On top of that, IT leadership is tasking DevOps teams to find systems, like an &lt;a href="https://konghq.com/learning-center/api-gateway/?utm_source=devto&amp;amp;utm_medium=syndication&amp;amp;utm_campaign=community" rel="noopener noreferrer"&gt;API gateway&lt;/a&gt; or Kubernetes ingress controller, to support API traffic growth while minimizing costs.&lt;/p&gt;

&lt;p&gt;API gateways are crucial components of &lt;a href="https://konghq.com/learning-center/microservices/microservices-architectures/?utm_source=devto&amp;amp;utm_medium=syndication&amp;amp;utm_campaign=community" rel="noopener noreferrer"&gt;microservice architectures&lt;/a&gt;. The API gateway acts as a single entry point into a distributed system, providing a unified interface for clients who don’t need to care (or know) that the system aggregates their API call response from multiple microservices.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9tntaojryh3uwlevxw1a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9tntaojryh3uwlevxw1a.png" alt="How an API Gateway Works"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Some everyday use cases for API gateways include:&lt;/p&gt;

&lt;p&gt;• Routing inbound requests to the appropriate microservice&lt;br&gt;
• Presenting a unified interface to a distributed architecture by aggregating responses from multiple backend services&lt;br&gt;
• Transforming microservice responses into the format required by the caller&lt;br&gt;
• Implementing non-functional/policy concerns such as authentication, logging, monitoring and observability, rate-limiting, IP filtering, and attack mitigation&lt;br&gt;
• Facilitating deployment strategies such as blue/green or canary releases&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;API gateways can simplify the development and maintenance of a microservice architecture. As a result, freeing up development teams to focus on the business logic of individual components.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Like &lt;a href="https://konghq.com/case-study/papa-johns-accelerates-time-to-market-with-kong?utm_source=devto&amp;amp;utm_medium=syndication&amp;amp;utm_campaign=community" rel="noopener noreferrer"&gt;Papa John’s&lt;/a&gt;, many companies select a Kubernetes API gateway at the beginning or partway through their transition to multi-cloud. Doing so makes it necessary to choose a solution that can function with on-prem services and the cloud.&lt;/p&gt;
&lt;h2&gt;
  
  
  Kubernetes
&lt;/h2&gt;

&lt;p&gt;Kubernetes is becoming the hosting platform of choice for distributed architectures. It offers auto-scaling, fault tolerance and zero-downtime deployments out of the box.&lt;/p&gt;

&lt;p&gt;By providing a widely accepted, standard approach with a carefully designed API, Kubernetes has spawned a thriving ecosystem of products and tools that make it much easier to deploy and maintain complex systems.&lt;/p&gt;
&lt;h2&gt;
  
  
  Kubernetes Ingress Controller
&lt;/h2&gt;

&lt;p&gt;As a native Kubernetes application, Kong is installed and managed precisely as any other Kubernetes resource. It integrates well with other CNCF projects and automatically updates itself with zero downtime in response to cluster events like pod deployments. There’s also a great &lt;a href="https://konghq.com/products/kong-gateway/kong-plugins/?utm_source=devto&amp;amp;utm_medium=syndication&amp;amp;utm_campaign=community" rel="noopener noreferrer"&gt;plugin ecosystem&lt;/a&gt; and native gRPC support.&lt;/p&gt;

&lt;p&gt;This article will walk through how easy it is to set up the open source &lt;a href="https://github.com/Kong/kubernetes-ingress-controller#kong-for-kubernetes" rel="noopener noreferrer"&gt;Kong Ingress Controller&lt;/a&gt; as a Kubernetes API gateway on a cluster.&lt;/p&gt;
&lt;h2&gt;
  
  
  Use Case: Routing API Calls to Backend Services
&lt;/h2&gt;

&lt;p&gt;To keep this article to a manageable size, I will only cover a single, straightforward use case.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft0zr2fvjy9a9vsil3u2n.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft0zr2fvjy9a9vsil3u2n.png" alt="Kong foo/bar routing"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I will create a Kubernetes cluster, deploy two dummy microservices, “foo” and “bar,” install and configure Kong to route inbound calls to &lt;code&gt;/foo&lt;/code&gt; to the foo microservice and send calls to &lt;code&gt;/bar&lt;/code&gt; to the bar microservice.&lt;/p&gt;

&lt;p&gt;The information in this post barely scratches the surface of what you can do with Kong, but it’s a good starting point.&lt;/p&gt;
&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;There are a few things you’ll need to work through in this article.&lt;/p&gt;

&lt;p&gt;I’m going to create a “real” Kubernetes cluster on DigitalOcean because it’s quick and easy, and I like to keep things as close to real-world scenarios as possible. If you want to work locally, you can use minikube or KinD. You will need to fake a load-balancer, though, either using the minikube tunnel or setting up a port forward to the API gateway.&lt;/p&gt;

&lt;p&gt;For DigitalOcean, you will need:&lt;/p&gt;

&lt;p&gt;• A DigitalOcean account&lt;br&gt;
• A DigitalOcean API token with read and write scopes&lt;br&gt;
• The doctl command-line tool&lt;/p&gt;

&lt;p&gt;To build and push docker images representing our microservices, you will need:&lt;/p&gt;

&lt;p&gt;• Docker&lt;br&gt;
• An account on Docker Hub&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Note: Optional because you can deploy the images I’ve already created.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;You will also need kubectl to access the Kubernetes cluster.&lt;/p&gt;
&lt;h2&gt;
  
  
  Setting Up doctl
&lt;/h2&gt;

&lt;p&gt;After installing &lt;code&gt;doctl&lt;/code&gt;, you’ll need to authenticate using the DigitalOcean API token:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="mi"&gt;2&lt;/span&gt;
&lt;span class="mi"&gt;3&lt;/span&gt;
&lt;span class="mi"&gt;4&lt;/span&gt;
&lt;span class="nx"&gt;$&lt;/span&gt; &lt;span class="nx"&gt;doctl&lt;/span&gt; &lt;span class="nx"&gt;auth&lt;/span&gt; &lt;span class="nx"&gt;init&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="nx"&gt;Enter&lt;/span&gt; &lt;span class="nx"&gt;your&lt;/span&gt; &lt;span class="nx"&gt;access&lt;/span&gt; &lt;span class="nx"&gt;token&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="o"&gt;&amp;lt;--&lt;/span&gt; &lt;span class="nx"&gt;paste&lt;/span&gt; &lt;span class="nx"&gt;your&lt;/span&gt; &lt;span class="nx"&gt;API&lt;/span&gt; &lt;span class="nx"&gt;token&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;when&lt;/span&gt; &lt;span class="nx"&gt;prompted&lt;/span&gt;
&lt;span class="nx"&gt;Validating&lt;/span&gt; &lt;span class="nx"&gt;token&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt; &lt;span class="nx"&gt;OK&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Create Kubernetes Cluster
&lt;/h2&gt;

&lt;p&gt;Now that you have authenticated &lt;code&gt;doctl&lt;/code&gt;, you can create your Kubernetes cluster with this command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;$&lt;/span&gt; &lt;span class="nx"&gt;doctl&lt;/span&gt; &lt;span class="nx"&gt;kubernetes&lt;/span&gt; &lt;span class="nx"&gt;cluster&lt;/span&gt; &lt;span class="nx"&gt;create&lt;/span&gt; &lt;span class="nx"&gt;mycluster&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="nx"&gt;size&lt;/span&gt; &lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="nx"&gt;vcpu&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="nx"&gt;gb&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Note: The command spins up a Kubernetes cluster on DigitalOcean. Doing so will incur charges (approximately $0.01/hour, at the time of writing) as long as it is running. Please remember to destroy any resources you create when you finish with them.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The command creates a cluster with a single worker node of the smallest viable size in the New York data center. It’s the smallest and simplest cluster (and also the cheapest to run). You can explore other options by running &lt;code&gt;doctl kubernetes --help&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The command will take several minutes to complete, and you should see an output like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;
&lt;span class="mi"&gt;2&lt;/span&gt;
&lt;span class="mi"&gt;3&lt;/span&gt;
&lt;span class="mi"&gt;4&lt;/span&gt;
&lt;span class="mi"&gt;5&lt;/span&gt;
&lt;span class="mi"&gt;6&lt;/span&gt;
&lt;span class="mi"&gt;7&lt;/span&gt;
&lt;span class="mi"&gt;8&lt;/span&gt;
&lt;span class="nx"&gt;$&lt;/span&gt; &lt;span class="nx"&gt;doctl&lt;/span&gt; &lt;span class="nx"&gt;kubernetes&lt;/span&gt; &lt;span class="nx"&gt;cluster&lt;/span&gt; &lt;span class="nx"&gt;create&lt;/span&gt; &lt;span class="nx"&gt;mycluster&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="nx"&gt;size&lt;/span&gt; &lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="nx"&gt;vcpu&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="nx"&gt;gb&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="nx"&gt;Notice&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Cluster&lt;/span&gt; &lt;span class="nx"&gt;is&lt;/span&gt; &lt;span class="nx"&gt;provisioning&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;waiting&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="nx"&gt;cluster&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="nx"&gt;be&lt;/span&gt; &lt;span class="nx"&gt;running&lt;/span&gt;
&lt;span class="p"&gt;....................................................&lt;/span&gt;
&lt;span class="nx"&gt;Notice&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Cluster&lt;/span&gt; &lt;span class="nx"&gt;created&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;fetching&lt;/span&gt; &lt;span class="nx"&gt;credentials&lt;/span&gt;
&lt;span class="nx"&gt;Notice&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Adding&lt;/span&gt; &lt;span class="nx"&gt;cluster&lt;/span&gt; &lt;span class="nx"&gt;credentials&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="nx"&gt;kubeconfig&lt;/span&gt; &lt;span class="nx"&gt;file&lt;/span&gt; &lt;span class="nx"&gt;found&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/Users/david/.kube/config&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="nx"&gt;Notice&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Setting&lt;/span&gt; &lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;context&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;nyc1&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;mycluster&lt;/span&gt;
&lt;span class="nx"&gt;ID&lt;/span&gt;                                      &lt;span class="nx"&gt;Name&lt;/span&gt;         &lt;span class="nx"&gt;Region&lt;/span&gt;    &lt;span class="nx"&gt;Version&lt;/span&gt;        &lt;span class="nx"&gt;Auto&lt;/span&gt; &lt;span class="nx"&gt;Upgrade&lt;/span&gt;    &lt;span class="nx"&gt;Status&lt;/span&gt;     &lt;span class="nx"&gt;Node&lt;/span&gt; &lt;span class="nx"&gt;Pools&lt;/span&gt;
&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="nx"&gt;cf2159a&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;01&lt;/span&gt;&lt;span class="nx"&gt;c1&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;423&lt;/span&gt;&lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;907&lt;/span&gt;&lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;51&lt;/span&gt;&lt;span class="nx"&gt;f19c3f9a01&lt;/span&gt;    &lt;span class="nx"&gt;mycluster&lt;/span&gt;    &lt;span class="nx"&gt;nyc1&lt;/span&gt;      &lt;span class="mf"&gt;1.20&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="k"&gt;do&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;    &lt;span class="kc"&gt;false&lt;/span&gt;           &lt;span class="nx"&gt;running&lt;/span&gt;    &lt;span class="nx"&gt;mycluster&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;pool&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, the command automatically adds cluster credentials and a context to the &lt;code&gt;~/.kube/config file&lt;/code&gt;, so you should be able to access your cluster using kubectl:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;
&lt;span class="mi"&gt;2&lt;/span&gt;
&lt;span class="mi"&gt;3&lt;/span&gt;
&lt;span class="mi"&gt;4&lt;/span&gt;
&lt;span class="mi"&gt;5&lt;/span&gt;
&lt;span class="mi"&gt;6&lt;/span&gt;
&lt;span class="nx"&gt;$&lt;/span&gt; &lt;span class="nx"&gt;kubectl&lt;/span&gt; &lt;span class="kd"&gt;get&lt;/span&gt; &lt;span class="nx"&gt;namespace&lt;/span&gt;
&lt;span class="nx"&gt;NAME&lt;/span&gt;              &lt;span class="nx"&gt;STATUS&lt;/span&gt;   &lt;span class="nx"&gt;AGE&lt;/span&gt;
&lt;span class="k"&gt;default&lt;/span&gt;           &lt;span class="nx"&gt;Active&lt;/span&gt;   &lt;span class="mi"&gt;24&lt;/span&gt;&lt;span class="nx"&gt;m&lt;/span&gt;
&lt;span class="nx"&gt;kube&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;lease&lt;/span&gt;   &lt;span class="nx"&gt;Active&lt;/span&gt;   &lt;span class="mi"&gt;24&lt;/span&gt;&lt;span class="nx"&gt;m&lt;/span&gt;
&lt;span class="nx"&gt;kube&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="kr"&gt;public&lt;/span&gt;       &lt;span class="nx"&gt;Active&lt;/span&gt;   &lt;span class="mi"&gt;24&lt;/span&gt;&lt;span class="nx"&gt;m&lt;/span&gt;
&lt;span class="nx"&gt;kube&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;system&lt;/span&gt;       &lt;span class="nx"&gt;Active&lt;/span&gt;   &lt;span class="mi"&gt;24&lt;/span&gt;&lt;span class="nx"&gt;m&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Create Dummy Microservices
&lt;/h2&gt;

&lt;p&gt;To represent backend microservices, I’m going to use a trivial Python Flask application that returns a JSON string:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;foo.py&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;
&lt;span class="mi"&gt;2&lt;/span&gt;
&lt;span class="mi"&gt;3&lt;/span&gt;
&lt;span class="mi"&gt;4&lt;/span&gt;
&lt;span class="mi"&gt;5&lt;/span&gt;
&lt;span class="mi"&gt;6&lt;/span&gt;
&lt;span class="mi"&gt;7&lt;/span&gt;
&lt;span class="mi"&gt;8&lt;/span&gt;
&lt;span class="mi"&gt;9&lt;/span&gt;
&lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="nx"&gt;flask&lt;/span&gt; &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Flask&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Flask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;__name__&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/foo&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nx"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;{"msg":"Hello from the foo microservice"}&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nx"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;__main__&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;debug&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nx"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;host&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;0.0.0.0&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This Dockerfile builds a docker image you can deploy:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Dockerfile&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;FROM&lt;/span&gt; &lt;span class="nx"&gt;python&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;alpine&lt;/span&gt;

&lt;span class="nx"&gt;WORKDIR&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;app&lt;/span&gt;

&lt;span class="nx"&gt;RUN&lt;/span&gt; &lt;span class="nx"&gt;echo&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Flask==1.1.1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;requirements&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;txt&lt;/span&gt;
&lt;span class="nx"&gt;RUN&lt;/span&gt; &lt;span class="nx"&gt;pip&lt;/span&gt; &lt;span class="nx"&gt;install&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt; &lt;span class="nx"&gt;requirements&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;txt&lt;/span&gt;
&lt;span class="nx"&gt;COPY&lt;/span&gt; &lt;span class="nx"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;py&lt;/span&gt; &lt;span class="p"&gt;.&lt;/span&gt;

&lt;span class="nx"&gt;EXPOSE&lt;/span&gt; &lt;span class="mi"&gt;5000&lt;/span&gt;

&lt;span class="nx"&gt;CMD&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;python&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;foo.py&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The files for our “foo” and “bar” services are almost identical, so I’m only going to show the “foo” files here. &lt;/p&gt;

&lt;p&gt;This gist contains files and a script to build &lt;code&gt;foo&lt;/code&gt; and &lt;code&gt;bar&lt;/code&gt; microservices docker images and push them to Docker Hub as:&lt;/p&gt;

&lt;p&gt;• digitalronin/foo-microservice:0.1&lt;br&gt;
• digitalronin/bar-microservice:0.1&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Note: You don’t have to build and push these images. You can just use the ones I’ve already created.&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Deploy Dummy Microservices
&lt;/h2&gt;

&lt;p&gt;You’ll need a manifest that defines a Deployment and a Service for each microservice, both for “foo” and “bar.” The manifest for “foo” (again, I’m only showing the “foo” example here, since the “bar” file is nearly identical) would look like this:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;foo.yaml&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;apiVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;apps&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;v1&lt;/span&gt;
&lt;span class="nx"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Deployment&lt;/span&gt;
&lt;span class="nx"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
  &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;foo&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;deployment&lt;/span&gt;
&lt;span class="nx"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
  &lt;span class="nx"&gt;replicas&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
  &lt;span class="nx"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nx"&gt;matchLabels&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;foo&lt;/span&gt;
  &lt;span class="nx"&gt;template&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nx"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="nx"&gt;labels&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;foo&lt;/span&gt;
    &lt;span class="nx"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="nx"&gt;containers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;api&lt;/span&gt;
        &lt;span class="nx"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;digitalronin&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;foo&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;microservice&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;0.1&lt;/span&gt;
        &lt;span class="nx"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;containerPort&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;5000&lt;/span&gt;
&lt;span class="o"&gt;---&lt;/span&gt;
&lt;span class="nx"&gt;apiVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;v1&lt;/span&gt;
&lt;span class="nx"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Service&lt;/span&gt;
&lt;span class="nx"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
  &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;foo&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;service&lt;/span&gt;
  &lt;span class="nx"&gt;labels&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;foo&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;service&lt;/span&gt;
&lt;span class="nx"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
  &lt;span class="nx"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
  &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;port&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;5000&lt;/span&gt;
    &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;http&lt;/span&gt;
    &lt;span class="nx"&gt;targetPort&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;5000&lt;/span&gt;
  &lt;span class="nx"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;foo&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This gist has manifests for both microservices, which you can download and deploy to your cluster like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;$&lt;/span&gt; &lt;span class="nx"&gt;kubectl&lt;/span&gt; &lt;span class="nx"&gt;apply&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;f&lt;/span&gt; &lt;span class="nx"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;yaml&lt;/span&gt;
&lt;span class="nx"&gt;$&lt;/span&gt; &lt;span class="nx"&gt;kubectl&lt;/span&gt; &lt;span class="nx"&gt;apply&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;f&lt;/span&gt; &lt;span class="nx"&gt;bar&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;yaml&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Access the Services
&lt;/h2&gt;

&lt;p&gt;You can check that the microservices are running correctly using a port forward:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;$&lt;/span&gt; &lt;span class="nx"&gt;kubectl&lt;/span&gt; &lt;span class="nx"&gt;port&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;forward&lt;/span&gt; &lt;span class="nx"&gt;service&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;foo&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;service&lt;/span&gt; &lt;span class="mi"&gt;5000&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;5000&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, in a different terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;
&lt;span class="mi"&gt;2&lt;/span&gt;
&lt;span class="nx"&gt;$&lt;/span&gt; &lt;span class="nx"&gt;curl&lt;/span&gt; &lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="c1"&gt;//localhost:5000/foo&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;msg&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hello from the foo microservice&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ditto for &lt;code&gt;bar&lt;/code&gt;, also using port 5000.&lt;/p&gt;

&lt;h2&gt;
  
  
  Install Kong for Kubernetes
&lt;/h2&gt;

&lt;p&gt;Now that you have our two microservices running in our Kubernetes cluster, let’s install Kong.&lt;/p&gt;

&lt;p&gt;There are several options for this, which you will find in the documentation. I’m going to apply the manifest directly, like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;$&lt;/span&gt; &lt;span class="nx"&gt;kubectl&lt;/span&gt; &lt;span class="nx"&gt;create&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;f&lt;/span&gt; &lt;span class="nx"&gt;https&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="c1"&gt;//bit.ly/k4k8s&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The last few lines of output should look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="nx"&gt;service&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;kong&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;proxy&lt;/span&gt; &lt;span class="nx"&gt;created&lt;/span&gt;
&lt;span class="nx"&gt;service&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;kong&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;validation&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;webhook&lt;/span&gt; &lt;span class="nx"&gt;created&lt;/span&gt;
&lt;span class="nx"&gt;deployment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;apps&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;ingress&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;kong&lt;/span&gt; &lt;span class="nx"&gt;created&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Note: You may receive several API deprecation warnings at this point, which you can ignore. Kong’s choice of API versions allows Kong Ingress Controller to support the broadest range of Kubernetes versions possible.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Installing Kong will create a DigitalOcean load balancer. It’s the internet-facing endpoint to which you will make API calls to access our microservices.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Note: DigitalOcean load balancers incur charges, so please remember to delete your load balancer along with your cluster when you are finished.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Creating the load balancer will take a minute or two. You can monitor its progress like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;$&lt;/span&gt; &lt;span class="nx"&gt;kubectl&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt; &lt;span class="nx"&gt;kong&lt;/span&gt; &lt;span class="kd"&gt;get&lt;/span&gt; &lt;span class="nx"&gt;service&lt;/span&gt; &lt;span class="nx"&gt;kong&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;proxy&lt;/span&gt;
&lt;span class="nx"&gt;NAME&lt;/span&gt;                      &lt;span class="nx"&gt;TYPE&lt;/span&gt;           &lt;span class="nx"&gt;CLUSTER&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;IP&lt;/span&gt;      &lt;span class="nx"&gt;EXTERNAL&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;IP&lt;/span&gt;   &lt;span class="nc"&gt;PORT&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;S&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;                      &lt;span class="nx"&gt;AGE&lt;/span&gt;
&lt;span class="nx"&gt;kong&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;proxy&lt;/span&gt;                &lt;span class="nx"&gt;LoadBalancer&lt;/span&gt;   &lt;span class="mf"&gt;10.245&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mf"&gt;14.22&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;pending&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;     &lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;32073&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;TCP&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;443&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;30537&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;TCP&lt;/span&gt;   &lt;span class="mi"&gt;71&lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once the system creates the load balancer, the &lt;code&gt;EXTERNAL-IP&lt;/code&gt; value will change from &lt;code&gt;&amp;lt;pending&amp;gt;&lt;/code&gt; to a real IP address:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;$&lt;/span&gt; &lt;span class="nx"&gt;kubectl&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt; &lt;span class="nx"&gt;kong&lt;/span&gt; &lt;span class="kd"&gt;get&lt;/span&gt; &lt;span class="nx"&gt;service&lt;/span&gt; &lt;span class="nx"&gt;kong&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;proxy&lt;/span&gt;
&lt;span class="nx"&gt;NAME&lt;/span&gt;                      &lt;span class="nx"&gt;TYPE&lt;/span&gt;           &lt;span class="nx"&gt;CLUSTER&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;IP&lt;/span&gt;      &lt;span class="nx"&gt;EXTERNAL&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;IP&lt;/span&gt;     &lt;span class="nc"&gt;PORT&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;S&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;                      &lt;span class="nx"&gt;AGE&lt;/span&gt;
&lt;span class="nx"&gt;kong&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;proxy&lt;/span&gt;                &lt;span class="nx"&gt;LoadBalancer&lt;/span&gt;   &lt;span class="mf"&gt;10.245&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mf"&gt;14.22&lt;/span&gt;    &lt;span class="mf"&gt;167.172&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mf"&gt;7.192&lt;/span&gt;   &lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;32073&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;TCP&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;443&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;30537&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;TCP&lt;/span&gt;   &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="nx"&gt;m45s&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For convenience, let’s export that IP number as an environment variable:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;$&lt;/span&gt; &lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="nx"&gt;PROXY_IP&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;167.172&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mf"&gt;7.192&lt;/span&gt; &lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;---&lt;/span&gt; &lt;span class="nx"&gt;use&lt;/span&gt; &lt;span class="nx"&gt;your&lt;/span&gt; &lt;span class="nx"&gt;own&lt;/span&gt; &lt;span class="nx"&gt;EXTERNAL&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;IP&lt;/span&gt; &lt;span class="nx"&gt;number&lt;/span&gt; &lt;span class="nx"&gt;here&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you can check that Kong is working:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;$&lt;/span&gt; &lt;span class="nx"&gt;curl&lt;/span&gt; &lt;span class="nx"&gt;$PROXY_IP&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;message&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;no Route matched with those values&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Note: It’s the correct response because you haven’t yet told Kong what to do with any API calls it receives.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Configure Kong Gateway
&lt;/h2&gt;

&lt;p&gt;You can use Ingress resources like this to configure Kong to route API calls to the microservices:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;foo-ingress.yaml&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;apiVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;networking&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;k8s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;io&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;v1&lt;/span&gt;
&lt;span class="nx"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Ingress&lt;/span&gt;
&lt;span class="nx"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
  &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;foo&lt;/span&gt;
  &lt;span class="nx"&gt;namespace&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt;

&lt;span class="nx"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
  &lt;span class="nx"&gt;ingressClassName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;kong&lt;/span&gt;
  &lt;span class="nx"&gt;rules&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
  &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="nx"&gt;paths&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;foo&lt;/span&gt;
        &lt;span class="nx"&gt;pathType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Prefix&lt;/span&gt;
        &lt;span class="nx"&gt;backend&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
          &lt;span class="nx"&gt;service&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;foo&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;service&lt;/span&gt;
            &lt;span class="nx"&gt;port&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
              &lt;span class="nx"&gt;number&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;5000&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This gist defines ingresses for both microservices. Download and apply them:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;$&lt;/span&gt; &lt;span class="nx"&gt;kubectl&lt;/span&gt; &lt;span class="nx"&gt;apply&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;f&lt;/span&gt; &lt;span class="nx"&gt;foo&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;ingress&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;yaml&lt;/span&gt;
&lt;span class="nx"&gt;$&lt;/span&gt; &lt;span class="nx"&gt;kubectl&lt;/span&gt; &lt;span class="nx"&gt;apply&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;f&lt;/span&gt; &lt;span class="nx"&gt;bar&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;ingress&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;yaml&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, Kong will route calls to &lt;code&gt;/foo&lt;/code&gt; to the foo microservice and &lt;code&gt;/bar&lt;/code&gt; to bar.&lt;/p&gt;

&lt;p&gt;You can check this using curl:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;$&lt;/span&gt; &lt;span class="nx"&gt;curl&lt;/span&gt; &lt;span class="nx"&gt;$PROXY_IP&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;foo&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;msg&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hello from the foo microservice&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;$&lt;/span&gt; &lt;span class="nx"&gt;curl&lt;/span&gt; &lt;span class="nx"&gt;$PROXY_IP&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;bar&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;msg&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hello from the bar microservice&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  What Else Can You Do?
&lt;/h2&gt;

&lt;p&gt;In this article, I have:&lt;/p&gt;

&lt;p&gt;• Deployed a Kubernetes cluster on DigitalOcean&lt;br&gt;
• Created Docker images for two dummy microservices, “foo” and “bar”&lt;br&gt;
• Deployed the microservices to the Kubernetes cluster&lt;br&gt;
• Installed the Kong Ingress Controller&lt;br&gt;
• Configured Kong to route API calls to the appropriate backend microservice&lt;/p&gt;

&lt;p&gt;I’ve demonstrated one simple use of Kong, but it’s only a starting point. With Kong for Kubernetes, here are several examples of other things you can do:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Authentication&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;By adding an authentication plugin to Kong, you can require your API callers to provide a valid JSON Web Token (JWT) and check each call against an Access Control List (ACL) to ensure callers are entitled to perform the relevant operations.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Certificate management&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You can enable integration with cert-manager to provision and auto-renew SSL certificates for your API endpoints so that all your API traffic is encrypted as it travels over the public internet.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;gRPC support&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Kong natively supports gRPC, so it’s easy to add gRPC support to your API.&lt;/p&gt;

&lt;p&gt;You can do a lot more with Kong, and I’d encourage you to look at the documentation and start to explore some of the other features.&lt;/p&gt;

&lt;p&gt;The API gateway is a crucial part of a microservices architecture, and the Kong Ingress Controller is well suited for this role in a Kubernetes cluster. You can manage it in the same way as any other Kubernetes resource.&lt;/p&gt;
&lt;h2&gt;
  
  
  Cleanup
&lt;/h2&gt;

&lt;p&gt;Don’t forget to destroy your Kubernetes cluster when you are finished with it so that you don’t incur unnecessary charges:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="mi"&gt;2&lt;/span&gt;
&lt;span class="mi"&gt;3&lt;/span&gt;
&lt;span class="mi"&gt;4&lt;/span&gt;
&lt;span class="mi"&gt;5&lt;/span&gt;
&lt;span class="mi"&gt;6&lt;/span&gt;
&lt;span class="nx"&gt;$&lt;/span&gt; &lt;span class="nx"&gt;kubectl&lt;/span&gt; &lt;span class="k"&gt;delete&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;f&lt;/span&gt; &lt;span class="nx"&gt;https&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="c1"&gt;//bit.ly/k4k8s  # &amp;lt;-- this will destroy the load-balancer&lt;/span&gt;

&lt;span class="nx"&gt;$&lt;/span&gt; &lt;span class="nx"&gt;doctl&lt;/span&gt; &lt;span class="nx"&gt;kubernetes&lt;/span&gt; &lt;span class="nx"&gt;cluster&lt;/span&gt; &lt;span class="k"&gt;delete&lt;/span&gt; &lt;span class="nx"&gt;mycluster&lt;/span&gt;
&lt;span class="nx"&gt;Warning&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Are&lt;/span&gt; &lt;span class="nx"&gt;you&lt;/span&gt; &lt;span class="nx"&gt;sure&lt;/span&gt; &lt;span class="nx"&gt;you&lt;/span&gt; &lt;span class="nx"&gt;want&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="k"&gt;delete&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt; &lt;span class="nx"&gt;Kubernetes&lt;/span&gt; &lt;span class="nx"&gt;cluster&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;y&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;N&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;y&lt;/span&gt;
&lt;span class="nx"&gt;Notice&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Cluster&lt;/span&gt; &lt;span class="nx"&gt;deleted&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;removing&lt;/span&gt; &lt;span class="nx"&gt;credentials&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Note: If you delete the cluster first, the load balancer will be left behind. You can delete any leftover resources via the DigitalOcean web interface.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Thanks for walking through this tutorial with us. It was originally published on our blog: &lt;a href="https://bit.ly/316W3zw" rel="noopener noreferrer"&gt;https://bit.ly/316W3zw&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Authentication with Kong's JWT Plugin</title>
      <dc:creator>Julia Salem</dc:creator>
      <pubDate>Mon, 15 Mar 2021 22:38:31 +0000</pubDate>
      <link>https://forem.com/kong/service-authentication-with-kong-s-jwt-plugin-1knm</link>
      <guid>https://forem.com/kong/service-authentication-with-kong-s-jwt-plugin-1knm</guid>
      <description>&lt;p&gt;As you build and maintain more applications, your authentication strategy becomes increasingly important. It may also be top of mind for your boss since technology leaders cited “improve application security” as one of their top priorities in this year’s &lt;a href="https://konghq.com/resources/digital-innovation-benchmark-2021/?utm_source=devto&amp;amp;utm_medium=syndication&amp;amp;utm_campaign=community"&gt;Digital Innovation Benchmark&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The Kong Gateway &lt;a href="https://docs.konghq.com/hub/kong-inc/jwt/?utm_source=devto&amp;amp;utm_medium=syndication&amp;amp;utm_campaign=community"&gt;JWT plugin&lt;/a&gt; is one strategy for &lt;a href="https://konghq.com/learning-center/api-gateway/api-gateway-authentication/?utm_source=devto&amp;amp;utm_medium=syndication&amp;amp;utm_campaign=community"&gt;API gateway authentication&lt;/a&gt;. JWT simplifies authentication setup, allowing you to focus more on coding and less on security.&lt;/p&gt;

&lt;h2&gt;
  
  
  Authentication Is Tough
&lt;/h2&gt;

&lt;p&gt;You know you need a secure front door to your system. If requests don’t have the right credentials, the door should remain locked. If they do have the proper credentials, the entry should be smooth. &lt;/p&gt;

&lt;p&gt;But how do you verify that credentials are authentic? And how do you make sure there aren’t other ways for those without the right credentials to get into your system?&lt;/p&gt;

&lt;p&gt;Let’s walk through those scenarios as I demonstrate how to secure a service (in this case, an API server) with &lt;a href="https://konghq.com/kong/?utm_source=devto&amp;amp;utm_medium=syndication&amp;amp;utm_campaign=community"&gt;Kong Gateway&lt;/a&gt; and its JWT plugin. I’ll cover all the steps to set up, configure and test the service — giving you the foundational knowledge needed to implement these tools independently.&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/OjF95vVldxY"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Core Concepts
&lt;/h2&gt;

&lt;p&gt;First, let’s cover the core technologies. If you’re already familiar with these and just want to get started, feel free to skip ahead.&lt;/p&gt;

&lt;h3&gt;
  
  
  What Is Kong Gateway?
&lt;/h3&gt;

&lt;p&gt;As more companies move from monolithic systems to microservices, a decoupled front-line API gateway to those services — providing authentication, traffic control, request and response transformation — becomes increasingly crucial. Kong Gateway, which is open source, serves as that thin layer between your users and your upstream microservices.&lt;/p&gt;

&lt;h3&gt;
  
  
  What Is JWT?
&lt;/h3&gt;

&lt;p&gt;The JSON Web Token (JWT) format lets two parties exchange secure claims. It’s a way of saying, “I am so-and-so, which should give me access to that resource. Here is my access token to prove it.” &lt;/p&gt;

&lt;p&gt;A JWT has a data payload signed by a trusted party to prevent spoofing. An authorizer verifies that the JWT token is authentic, allowing (or forbidding) access to that resource. Typically, a JWT payload is not encrypted; it’s open for the whole world to read. However, what’s critical is the authenticity of a token, which depends on a trusted party signing it.&lt;/p&gt;

&lt;h3&gt;
  
  
  What Does Kong's JWT API Gateway Plugin Do?
&lt;/h3&gt;

&lt;p&gt;In this approach, the plugin serves as the JWT authorizer. It authenticates the JWT in the HTTP request by verifying that token’s claims and ensuring a trusted party signed it. Then, depending on whether these steps were successful, Kong Gateway routes the upstream service request.&lt;/p&gt;

&lt;p&gt;Keep in mind that authentication in this context means validating the user’s credentials. That’s the job of the JWT plugin. There’s no way to know how a user got a valid JWT. The system just knows that the user has one and is presenting it for authentication. If the JWT is authentic, you can be confident that the user is who they say.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Basic Use Case
&lt;/h2&gt;

&lt;p&gt;In this basic use case, I have a login server that accepts login attempts with a user’s email and password. If the email/password checks out, the server generates and signs a JWT and hands it back to the user.&lt;/p&gt;

&lt;p&gt;With JWT in hand, the user tries to access our microservice: a simple API server with a single endpoint. Kong Gateway sits in front of your API server, using the JWT plugin for authentication. The user presents his JWT with his request.&lt;/p&gt;

&lt;p&gt;First, the plugin verifies the token’s authenticity. Next, it confirms the installation steps of the claims inside the payload. A common claim used is an expiration timestamp for the access token. It’s essentially saying, “This token is valid until this date and time.” So, the plugin will check the token’s expiration date.&lt;/p&gt;

&lt;p&gt;If the JWT passes all the necessary checks, Kong Gateway grants access to the requested server endpoint. Otherwise, it responds with &lt;code&gt;401 Unauthorized&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The approach is quite simple:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Set up a basic Node.js Express server with a single endpoint.&lt;/li&gt;
&lt;li&gt;Set up Kong Gateway as an API gateway to your server.&lt;/li&gt;
&lt;li&gt;Enable the JWT plugin to protect your server endpoint with JWT authentication.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  1. Set Up a Node.js Express Server and Endpoint
&lt;/h3&gt;

&lt;p&gt;On your local machine, create a folder for your project. Then, initialize a new Node.js project. In the following examples, I’ll use yarn, but you could use npm too:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;
&lt;span class="mi"&gt;3&lt;/span&gt;
&lt;span class="o"&gt;~&lt;/span&gt;&lt;span class="nx"&gt;$&lt;/span&gt; &lt;span class="nx"&gt;mkdir&lt;/span&gt; &lt;span class="nx"&gt;project&lt;/span&gt;
&lt;span class="o"&gt;~&lt;/span&gt;&lt;span class="nx"&gt;$&lt;/span&gt; &lt;span class="nx"&gt;cd&lt;/span&gt; &lt;span class="nx"&gt;project&lt;/span&gt;
&lt;span class="o"&gt;~&lt;/span&gt;&lt;span class="sr"&gt;/project$ yarn init  # Use all of the yarn defaults here&lt;/span&gt;&lt;span class="err"&gt;.
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, add Express to your project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="o"&gt;~&lt;/span&gt;&lt;span class="sr"&gt;/project$ yarn add expres&lt;/span&gt;&lt;span class="err"&gt;s
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In your project folder, create the entry point file, &lt;code&gt;index.js&lt;/code&gt;, which will spin up an Express server with a single endpoint. Allow a &lt;code&gt;GET&lt;/code&gt; request to &lt;code&gt;/&lt;/code&gt;, which will respond with the string, “Hello world!”&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="cm"&gt;/* PATH: ~/project/index.js
*/&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;express&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;server&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;port&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3000&lt;/span&gt;

&lt;span class="nx"&gt;server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Hello world!&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="nx"&gt;server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;port&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Server is listening on http://localhost:&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;port&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That was simple enough! Your single endpoint should log the request headers and then send “Hello world!” back to the client with a &lt;code&gt;200&lt;/code&gt; status.&lt;/p&gt;

&lt;p&gt;Start your server:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="o"&gt;~&lt;/span&gt;&lt;span class="sr"&gt;/project$ node index.j&lt;/span&gt;&lt;span class="err"&gt;s
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can use your browser to test this new endpoint by visiting &lt;code&gt;http://localhost:3000&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Your API server endpoint should be working now!&lt;/p&gt;

&lt;p&gt;Next, use &lt;a href="https://insomnia.rest/"&gt;Insomnia&lt;/a&gt; to send the request and inspect the response. Because of its usability, you’re going to want to use Insomnia exclusively once you start sending requests with a JWT.&lt;/p&gt;

&lt;p&gt;In Insomnia, create a &lt;code&gt;GET&lt;/code&gt; request to &lt;code&gt;http://localhost:3000&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In Insomnia, you should get a &lt;code&gt;200 OK&lt;/code&gt; with “Hello world!” in the response body.&lt;/p&gt;

&lt;p&gt;It looks like the API server is up and running. Now, it’s time to put Kong Gateway in front of it.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Set Up Kong Gateway
&lt;/h3&gt;

&lt;p&gt;I won’t cover the details here, but the &lt;a href="https://konghq.com/blog/set-up-kong-gateway/?utm_source=devto&amp;amp;utm_medium=syndication&amp;amp;utm_campaign=community"&gt;Kong Gateway installation steps&lt;/a&gt; may look different depending on your system. &lt;/p&gt;

&lt;p&gt;Once you’ve installed Kong, you’ll need to take a few additional steps.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;DB-Less Declarative Configuration&lt;/strong&gt;&lt;br&gt;
There are &lt;a href="https://docs.konghq.com/gateway-oss/2.3.x/db-less-and-declarative-config/?_ga=2.246640775.229196122.1615774344-852472749.1605808164&amp;amp;utm_source=devto&amp;amp;utm_medium=syndication&amp;amp;utm_campaign=community"&gt;two primary ways to configure Kong&lt;/a&gt;. Imperative configuration issues step-by-step configuration commands to Kong through its admin API. Meanwhile, declarative configuration stores the entire configuration in a single &lt;code&gt;.yml&lt;/code&gt; file then loads it into Kong upon startup. Additionally, you can configure Kong to hook into your database, providing more control over the different nodes it manages.&lt;/p&gt;

&lt;p&gt;For the simple setup example, I’ll use database-less declarative configuration. When you start up Kong, you’ll tell it where to find a &lt;code&gt;.yml&lt;/code&gt; file with all of the configuration declared within.&lt;/p&gt;

&lt;p&gt;In your project folder, run the following command, which generates an initial &lt;code&gt;kong.yml&lt;/code&gt; declarative configuration file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;
&lt;span class="mi"&gt;2&lt;/span&gt;
&lt;span class="mi"&gt;3&lt;/span&gt;
&lt;span class="mi"&gt;4&lt;/span&gt;
&lt;span class="mi"&gt;5&lt;/span&gt;
&lt;span class="mi"&gt;6&lt;/span&gt;
&lt;span class="mi"&gt;7&lt;/span&gt;
&lt;span class="mi"&gt;8&lt;/span&gt;
&lt;span class="mi"&gt;9&lt;/span&gt;
&lt;span class="o"&gt;~&lt;/span&gt;&lt;span class="sr"&gt;/project$ kong config ini&lt;/span&gt;&lt;span class="err"&gt;t
&lt;/span&gt;&lt;span class="o"&gt;~&lt;/span&gt;&lt;span class="sr"&gt;/project$ tree -L &lt;/span&gt;&lt;span class="err"&gt;1
&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;js&lt;/span&gt;
&lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="nx"&gt;kong&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;yml&lt;/span&gt;
&lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="nx"&gt;node_modules&lt;/span&gt;
&lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="kr"&gt;package&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;
&lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="nx"&gt;yarn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;lock&lt;/span&gt;
&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="nx"&gt;directory&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt; &lt;span class="nx"&gt;files&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, you’ll need to configure the system’s &lt;code&gt;kong.conf&lt;/code&gt; file before starting up Kong. If you’re working on Ubuntu, you’ll be working in &lt;code&gt;/etc/kong&lt;/code&gt;. Here is a template to copy over and then edit.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="o"&gt;~&lt;/span&gt;&lt;span class="sr"&gt;/project$ cd /&lt;/span&gt;&lt;span class="nx"&gt;etc&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;kong&lt;/span&gt;
&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;etc&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;kong$&lt;/span&gt; &lt;span class="nx"&gt;sudo&lt;/span&gt; &lt;span class="nx"&gt;su&lt;/span&gt;

&lt;span class="nx"&gt;root&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;etc&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;kong$&lt;/span&gt; &lt;span class="nx"&gt;tree&lt;/span&gt;
&lt;span class="p"&gt;.&lt;/span&gt;
&lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="nx"&gt;kong&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;conf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;default&lt;/span&gt;
&lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="nx"&gt;kong&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;logrotate&lt;/span&gt;
&lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="nx"&gt;directories&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="nx"&gt;files&lt;/span&gt;

&lt;span class="nx"&gt;root&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;etc&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;kong$&lt;/span&gt; &lt;span class="nx"&gt;cp&lt;/span&gt; &lt;span class="nx"&gt;kong&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;conf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;kong&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;conf&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There are only two edits you need to make in your &lt;code&gt;kong.conf&lt;/code&gt; file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nx"&gt;PATH&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;etc&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;kong&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;kong&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;conf&lt;/span&gt;

&lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nx"&gt;Around&lt;/span&gt; &lt;span class="nx"&gt;line&lt;/span&gt; &lt;span class="mi"&gt;839&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;uncomment&lt;/span&gt; &lt;span class="nx"&gt;and&lt;/span&gt; &lt;span class="kd"&gt;set&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="nx"&gt;off&lt;/span&gt;
&lt;span class="nx"&gt;database&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;off&lt;/span&gt;

&lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nx"&gt;Around&lt;/span&gt; &lt;span class="nx"&gt;line&lt;/span&gt; &lt;span class="mi"&gt;1023&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;uncomment&lt;/span&gt; &lt;span class="nx"&gt;and&lt;/span&gt; &lt;span class="kd"&gt;set&lt;/span&gt; &lt;span class="nx"&gt;an&lt;/span&gt; &lt;span class="nx"&gt;absolute&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="nx"&gt;kong&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;yml&lt;/span&gt;
&lt;span class="nx"&gt;declarative_config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sr"&gt;/PATH/&lt;/span&gt;&lt;span class="nx"&gt;TO&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;YOUR&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;project&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;kong&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;yml&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When Kong starts up, it will be in DB-less mode, meaning it will look to your project’s kong.yml file for a configuration.&lt;/p&gt;

&lt;p&gt;Finally, you’ll need to edit your &lt;code&gt;kong.yml&lt;/code&gt; file to set up a gateway in front of your API server “hello world” endpoint.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;
&lt;span class="mi"&gt;2&lt;/span&gt;
&lt;span class="mi"&gt;3&lt;/span&gt;
&lt;span class="mi"&gt;4&lt;/span&gt;
&lt;span class="mi"&gt;5&lt;/span&gt;
&lt;span class="mi"&gt;6&lt;/span&gt;
&lt;span class="mi"&gt;7&lt;/span&gt;
&lt;span class="mi"&gt;8&lt;/span&gt;
&lt;span class="mi"&gt;9&lt;/span&gt;
&lt;span class="mi"&gt;10&lt;/span&gt;
&lt;span class="mi"&gt;11&lt;/span&gt;
&lt;span class="mi"&gt;12&lt;/span&gt;
&lt;span class="mi"&gt;13&lt;/span&gt;
&lt;span class="cm"&gt;/* PATH: ~/project/kong.yml
*/&lt;/span&gt;

&lt;span class="nx"&gt;_format_version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;2.1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;

&lt;span class="nx"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;my&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;api&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;server&lt;/span&gt;
  &lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="c1"&gt;//localhost:3000/&lt;/span&gt;
&lt;span class="nx"&gt;routes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;api&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;requests&lt;/span&gt;
  &lt;span class="nx"&gt;service&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;my&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;api&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;server&lt;/span&gt;
  &lt;span class="nx"&gt;paths&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="sr"&gt;/ap&lt;/span&gt;&lt;span class="err"&gt;i
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let’s go over this.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;_format_version&lt;/code&gt; metadata specifies the version number of your declarative configuration format.&lt;/p&gt;

&lt;p&gt;Next, you define your service, which Kong describes as “an entity representing an external upstream API or microservice.” You can name your service &lt;code&gt;my-api-service&lt;/code&gt; and specify its URL — you’ll recall that the Express server listens for requests at &lt;code&gt;http://localhost:3000&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Next, define routes, which “determine how (and if) requests are sent to their Services after they reach Kong Gateway.” The (local) URL for Kong is &lt;code&gt;http://localhost:8000&lt;/code&gt;. You should declare your route so that Kong listens for requests at &lt;code&gt;http://localhost:8000/api&lt;/code&gt;, then routes to your service.&lt;/p&gt;

&lt;p&gt;Let’s see this in action. Make sure your Express server is running in a separate terminal. Then, start Kong.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="o"&gt;~&lt;/span&gt;&lt;span class="sr"&gt;/project$ sudo kong star&lt;/span&gt;&lt;span class="err"&gt;t
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In your browser, go to &lt;code&gt;http://localhost:8000/api&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Kong Gateway is up. Finally, add authentication.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Attach JWT Plugin to Kong Gateway
&lt;/h3&gt;

&lt;p&gt;To add the JWT plugin, add a “plugins” definition to your &lt;code&gt;kong.yml&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="cm"&gt;/* PATH: ~/project/kong.yml
*/&lt;/span&gt;

&lt;span class="nx"&gt;_format_version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;2.1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;

&lt;span class="nx"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;my&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;api&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;server&lt;/span&gt;
  &lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="c1"&gt;//localhost:3000/&lt;/span&gt;
&lt;span class="nx"&gt;routes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;api&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;requests&lt;/span&gt;
  &lt;span class="nx"&gt;service&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;my&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;api&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;server&lt;/span&gt;
  &lt;span class="nx"&gt;paths&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="sr"&gt;/ap&lt;/span&gt;&lt;span class="err"&gt;i
&lt;/span&gt;&lt;span class="nx"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;jwt&lt;/span&gt;
  &lt;span class="nx"&gt;service&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;my&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;api&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;server&lt;/span&gt;
  &lt;span class="nx"&gt;enabled&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
  &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nx"&gt;key_claim_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;kid&lt;/span&gt;
    &lt;span class="nx"&gt;claims_to_verify&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;exp&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, you can add the plugin named &lt;code&gt;jwt&lt;/code&gt; and attach it to your service called &lt;code&gt;my-api-server&lt;/code&gt;. For its &lt;a href="https://docs.konghq.com/hub/kong-inc/jwt/?_ga=2.207847185.229196122.1615774344-852472749.1605808164&amp;amp;utm_source=devto&amp;amp;utm_medium=syndication&amp;amp;utm_campaign=community#parameters"&gt;configuration options&lt;/a&gt;, tell the plugin to check the &lt;code&gt;exp&lt;/code&gt; value to verify that the access token has not expired.&lt;/p&gt;

&lt;p&gt;At this point, restart Kong and see what happens:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="o"&gt;~&lt;/span&gt;&lt;span class="sr"&gt;/project$ sudo kong restar&lt;/span&gt;&lt;span class="err"&gt;t
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The response is &lt;code&gt;401 Unauthorized&lt;/code&gt;. Excellent! Kong now requires a valid JWT for any requests to your API server. Next, you need to tell Kong what constitutes a valid JWT.&lt;/p&gt;

&lt;p&gt;In &lt;code&gt;kong.yml&lt;/code&gt;, you need to add a consumer and a credential. Kong describes consumers as being “associated with individuals using your Service, and can be used for tracking, access management, and more.” In a more elaborate setting, every one of your API users could be a consumer. That’s a use case you can read more about towards the end of this article. In this situation, your login server is your consumer. Your login server will be the entity generating JWTs and handing them out. Users who make a request to Kong will be holding a “login server” JWT.&lt;/p&gt;

&lt;p&gt;Edit your &lt;code&gt;kong.yml&lt;/code&gt; file by adding the “consumers” and “jwt_secrets” definitions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="mi"&gt;2&lt;/span&gt;
&lt;span class="mi"&gt;3&lt;/span&gt;
&lt;span class="mi"&gt;4&lt;/span&gt;
&lt;span class="mi"&gt;5&lt;/span&gt;
&lt;span class="mi"&gt;6&lt;/span&gt;
&lt;span class="mi"&gt;7&lt;/span&gt;
&lt;span class="mi"&gt;8&lt;/span&gt;
&lt;span class="mi"&gt;9&lt;/span&gt;
&lt;span class="mi"&gt;10&lt;/span&gt;
&lt;span class="mi"&gt;11&lt;/span&gt;
&lt;span class="mi"&gt;12&lt;/span&gt;
&lt;span class="mi"&gt;13&lt;/span&gt;
&lt;span class="mi"&gt;14&lt;/span&gt;
&lt;span class="mi"&gt;15&lt;/span&gt;
&lt;span class="mi"&gt;16&lt;/span&gt;
&lt;span class="mi"&gt;17&lt;/span&gt;
&lt;span class="mi"&gt;18&lt;/span&gt;
&lt;span class="mi"&gt;19&lt;/span&gt;
&lt;span class="mi"&gt;20&lt;/span&gt;
&lt;span class="mi"&gt;21&lt;/span&gt;
&lt;span class="mi"&gt;22&lt;/span&gt;
&lt;span class="mi"&gt;23&lt;/span&gt;
&lt;span class="mi"&gt;24&lt;/span&gt;
&lt;span class="mi"&gt;25&lt;/span&gt;
&lt;span class="mi"&gt;26&lt;/span&gt;
&lt;span class="cm"&gt;/* PATH: ~/project/kong.yml
*/&lt;/span&gt;

&lt;span class="nx"&gt;_format_version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;2.1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;

&lt;span class="nx"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;my&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;api&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;server&lt;/span&gt;
  &lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="c1"&gt;//localhost:3000/&lt;/span&gt;
&lt;span class="nx"&gt;routes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;api&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;requests&lt;/span&gt;
  &lt;span class="nx"&gt;service&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;my&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;api&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;server&lt;/span&gt;
  &lt;span class="nx"&gt;paths&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="sr"&gt;/ap&lt;/span&gt;&lt;span class="err"&gt;i
&lt;/span&gt;&lt;span class="nx"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;jwt&lt;/span&gt;
  &lt;span class="nx"&gt;service&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;my&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;api&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;server&lt;/span&gt;
  &lt;span class="nx"&gt;enabled&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
  &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nx"&gt;key_claim_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;kid&lt;/span&gt;
    &lt;span class="nx"&gt;claims_to_verify&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;exp&lt;/span&gt;
&lt;span class="nx"&gt;consumers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
  &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;username&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;login_server_issuer&lt;/span&gt;
&lt;span class="nx"&gt;jwt_secrets&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
  &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;consumer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;login_server_issuer&lt;/span&gt;
    &lt;span class="nx"&gt;secret&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;secret-hash-brown-bear-market-rate-limit&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You’ve added a new consumer, named &lt;code&gt;login_server_issuer&lt;/code&gt;. Then, you added a JWT API gateway credential for that consumer, which contains the secret used to sign JWTs for this consumer. Authentication requires two parts:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The &lt;code&gt;kid&lt;/code&gt; (key identifier) value in the JWT header, which is a unique identifier that lets the plugin determine which consumer allegedly issued this JWT&lt;/li&gt;
&lt;li&gt;Verification of the consumer’s secret – Was this the secret used to sign this JWT API gateway? If so, then this JWT is authentic.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Before continuing, remember to restart Kong:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="o"&gt;~&lt;/span&gt;&lt;span class="sr"&gt;/project$ sudo kong restar&lt;/span&gt;&lt;span class="err"&gt;t
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you want to generate a JWT for testing, you need the secret (which you have) and the key to use for the kid value. Kong gives us access to that value through its admin API at &lt;code&gt;http://localhost:8001&lt;/code&gt;. You send a &lt;code&gt;GET&lt;/code&gt; request to the admin API’s endpoint &lt;code&gt;/consumers/CONSUMER-USERNAME/jwt&lt;/code&gt;. This gives us information about this consumer’s JWT credential.&lt;/p&gt;

&lt;p&gt;As you inspect this credential’s information, you should see the JWT &lt;code&gt;secret&lt;/code&gt; and signing &lt;code&gt;algorithm&lt;/code&gt;. What you’re looking for, though, is the key. In the above example, that’s &lt;code&gt;1nzcMG9Xg7n1lLgmltHnkAmkt7yp4fjZ&lt;/code&gt;. This is what you use as the &lt;code&gt;kid&lt;/code&gt; value in the JWT header. The Kong plugin will see this &lt;code&gt;kid&lt;/code&gt; value, track down the associated consumer and secret, then make sure the JWT was signed with that secret.&lt;/p&gt;

&lt;p&gt;To test this, let’s start with the happy path. You need a JWT with a header that includes the correct kid value, signed with the right secret. For simplicity, let’s do this at jwt.io. Here, you can craft your payload, set the signing secret and then copy/paste the resulting JWT.&lt;/p&gt;

&lt;p&gt;In the payload, the &lt;code&gt;kid&lt;/code&gt; must match the &lt;code&gt;key&lt;/code&gt; value from above. Also, because you configured the plugin to check JWT token expiration, you should set the &lt;code&gt;exp&lt;/code&gt; (Unix timestamp) far into the future. The &lt;code&gt;name&lt;/code&gt; and &lt;code&gt;email&lt;/code&gt; are inconsequential; they just demonstrate that you can put other helpful data in the JWT payload.&lt;/p&gt;

&lt;p&gt;Lastly, include your JWT secret at the bottom for proper signing. The result is an encoded JWT.&lt;/p&gt;

&lt;p&gt;Back in Insomnia, you have your original request that resulted in &lt;code&gt;401&lt;/code&gt;. You need to add “Authorization” to that request. Choose “Auth – Bearer Token,” then paste in your encoded JWT from above.&lt;/p&gt;

&lt;p&gt;Now, with a valid JWT attached, resend the request.&lt;/p&gt;

&lt;p&gt;Your JWT should have been validated, and Kong routed us to the API server!&lt;/p&gt;

&lt;p&gt;If you look back at the terminal running the Express server, you’ll recall that you’re logging the request headers to the console. When the JWT plugin authenticates an access token, it writes some additional values to the upstream headers, namely the consumer id, username and credential identifier (the &lt;code&gt;key&lt;/code&gt; value).&lt;/p&gt;

&lt;p&gt;But what happens if your JWT is not valid? Let’s test and see.&lt;/p&gt;

&lt;p&gt;First, sign the JWT with a different secret. Back at jwt.io, keep the payload, but change the signing secret. Copy the resulting JWT to Insomnia, and send your request again. You’ll get a &lt;code&gt;401&lt;/code&gt; with “Invalid Signature.”&lt;/p&gt;

&lt;p&gt;If your secret is correct, but the &lt;code&gt;kid&lt;/code&gt; is incorrect, Kong won’t find an associated credential. Without that credential, there’s no way to find the secret for authenticating the JWT.&lt;/p&gt;

&lt;p&gt;Lastly, if the &lt;code&gt;exp&lt;/code&gt; value is in the past, then your JWT has expired. Just as you expected, you get the following response.&lt;/p&gt;

&lt;p&gt;And that’s it! You should be up and running with Kong Gateway and the JWT Plugin acting as an authentication layer in front of an API server.&lt;/p&gt;

&lt;h2&gt;
  
  
  Set It and Forget It
&lt;/h2&gt;

&lt;p&gt;Implementing authentication —and getting it right —is hard work. As microservices become the norm, delegating authentication makes more and more sense. “Rolling your own” implementation for JWT authentication can muddy a code base and still leave you wondering if you got it right. By using well-tested and community-adopted services that handle concerns like routing, logging or authentication, developers can shift their focus back to their projects’ unique needs.&lt;/p&gt;

&lt;p&gt;With that, you now have a solid foundation for getting started with Kong Gateway and the JWT plugin. It’s time to get to work.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Thanks for walking through this tutorial with us. It was originally published on our blog: &lt;a href="https://bit.ly/3eJGhCS"&gt;https://bit.ly/3eJGhCS&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>security</category>
      <category>apigateway</category>
      <category>authorization</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
