Introduction

:8000 on which Kong listens for incoming HTTP traffic from your clients,
and forwards it to your upstream services. This is the port that interests
us in this guide.

:8443 on which Kong listens for incoming HTTPS traffic. This port has a
similar behavior as the :8000 port, except that it expects HTTPS traffic
only. This port can be disabled via the configuration file.

In this document we cover routing capabilities of Kong by explaining in detail
how incoming requests on port :8000 are proxied to a configured upstream
service depending on their headers, URI, and HTTP method.

Terminology

API: This term refers to the API entity of Kong. You configure your APIs,
that point to your own upstream services, through the Admin API.

Plugin: This refers to Kong “plugins”, which are pieces of business logic
that run in the proxying lifecycle. Plugins can be configured through the
Admin API - either globally (all incoming traffic) or on a per-API basis.

Client or : Refers to the downstream client making requests to Kong’s
proxy port.

Upstream service: Refers to your own API/service sitting behind Kong, to
which client requests are forwarded.

Overview

From a high level perspective, Kong will listen for HTTP traffic on its
configured proxy port (8000 by default), recognize which upstream service is
being requested, run the configured plugins for that API, and forward the HTTP
request upstream to your own API or service.

When a client makes a request to the proxy port, Kong will decide to which
upstream service or API to route (or forward) the incoming request, depending
on the API configuration in Kong, which is managed via the Admin API. You can
configure APIs with various properties, but the three relevant ones for routing
incoming traffic are hosts, uris, and methods.

If Kong cannot determine to which upstream API a given request should be
routed, Kong will respond with:

HTTP/1.1404Not FoundContent-Type:application/jsonServer:kong/<x.x.x>{"message":"no API found with those values"}

This request instructs Kong to register an API named “my-api”, reachable at
“http://my-api.com”. It also specifies various routing properties, though note
that only one ofhosts, uris and methods is required.

Adding such an API would mean that you configured Kong to proxy all incoming
requests matching the specified hosts, uris, and methods to
http://example.com. Kong is a transparent proxy, and it will forward the
request to your upstream service untouched, with the exception of the addition
of various headers such as Connection.

Routing capabilities

Let’s now discuss how Kong matches a request to the configured hosts, uris
and methods properties (or fields) of your API. Note that all three of these
fields are optional, but at least one of them must be specified. For a
client request to match an API:

The request must include all of the configured fields

The values of the fields in the request must match at least one of the
configured values (While the field configurations accepts one or more values,
a request needs only one of the values to be considered a match)

Let’s go through a few examples. Consider an API configured like this:

All three of these requests satisfy all the conditions set in the API
definition.

However, the following requests would not match the configured conditions:

GET/HTTP/1.1Host:example.com

POST/fooHTTP/1.1Host:example.com

GET/fooHTTP/1.1Host:foo.com

All three of these requests satisfy only two of configured conditions. The
first request’s URI is not a match for any of the configured uris, same for
the second request’s HTTP method, and the third request’s Host header.

Now that we understand how the hosts, uris, and methods properties work
together, let’s explore each property individually.

Request Host header

Routing a request based on its Host header is the most straightforward way to
proxy traffic through Kong, as this is the intended usage of the HTTP Host
header. Kong makes it easy to do so via the hosts field of the API entity.

hosts accepts multiple values, which must be comma-separated when specifying
them via the Admin API:

The preserve_host property

When proxying, Kong’s default behavior is to set the upstream request’s Host
header to the hostname of the API’s upstream_url property. The
preserve_host field accepts a boolean flag instructing Kong not to do so.

For example, when the preserve_host property is not changed and an API is
configured like this:

Request URI

Another way for Kong to route a request to a given upstream service is to
specify a request URI via the uris property. To satisfy this field’s
condition, a client request’s URI must be prefixed with one of the values
of the uris field.

For each of these requests, Kong detects that their URI is prefixed with one of
the API’s uris values. By default, Kong would then forward the request
upstream with the untouched, same URI.

When proxying with URIs prefixes, the longest URIs get evaluated first.
This allow you to define two APIs with two URIs: /service and
/service/resource, and ensure that the former does not “shadow” the latter.

Evaluation order

As previously mentioned, Kong evaluates prefix URIs by length: the longest
prefix URIs are evaluated first. However, Kong will evaluate regex URIs based
on the order in which they are defined. This means that considering the
following APIs:

As usual, a request must still match an API’s hosts and methods properties
as well, and Kong will traverse your APIs until it finds one that matches
the most rules (see [Routing priorities][proxy-routing-priorities]).

Capturing groups

Capturing groups are also supported, and the matched group will be extracted
from the URI and available for plugins consumption. If we consider the
following regex:

/version/(?<version>\d+)/users/(?<user>\S+)

And the following request URI:

/version/1/users/john

Kong will consider the request URI a match, and if the overall API is matched
(considering hosts and methods fields), the extracted capturing groups
will be available from the plugins in the ngx.ctx variable:

Escaping special characters

Next, it is worth noting that characters found in regexes are often
reserved characters according to
RFC 3986 and as such,
should be percent-encoded. When configuring APIs with regex URIs via the
Admin API, be sure to URL encode your payload if necessary. For example,
with curl and using an application/x-www-form-urlencoded MIME type:

Note that curl does not automatically URL encode your payload, and note the
usage of --data-urlencode, which prevents the + character to be URL decoded
and interpreted as a space ` ` by Kong’s Admin API.

Last but not least - and still related to special characters commonly found in
PCRE sequences - we must consider the comma, which is used by Kong to delimit
several entries in the uris property. Because of this, commas used in a PCRE
sequence must be escaped, like so:

In the above example, two regex URIs are defined, and both of these URIs
contain a repeated escape sequence: \d+{1,3}. Because those two URIs are
separated via a comma delimiter, we must escape any comma present in the
regexes themselves to ensure Kong’s Admin API does not interpret them as a
separator.

Enabling this flag instructs Kong that when proxying this API, it should
not include the matching URI prefix in the upstream request’s URI. For
example, the following client’s request to the API configured as above:

GET/service/path/to/resourceHTTP/1.1Host:

Will cause Kong to send the following request to your upstream service:

GET/path/to/resourceHTTP/1.1Host:my-api.com

The same way, if a regex URI is defined on an API that has strip_uri enabled,
the entirety of the request URI matching sequence will be stripped. Example:

Request HTTP method

Starting with Kong 0.10, client requests can also be routed depending on their
HTTP method by specifying the methods field. By default, Kong will route a
request to an API regardless of its HTTP method. But when this field is set,
only requests with the specified HTTP methods will be matched.

This field also accepts multiple values. Here is an example of an API allowing
routing via GET and HEAD HTTP methods:

But would not match a POST or DELETE request. This allows for much more
granularity when configuring APIs and Plugins. For example, one could imagine
two APIs pointing to the same upstream service: one API allowing unlimited
unauthenticated GET requests, and a second API allowing only authenticated
and rate-limited POST requests (by applying the authentication and rate
limiting plugins to such requests).

Routing priorities

An API may define matching rules based on its hosts, uris, and methods
fields. For Kong to match an incoming request to an API, all existing fields
must be satisfied. However, Kong allows for quite some flexibility by allowing
two or more APIs to be configured with fields containing the same values - when
this occurs, Kong applies a priority rule.

The rule is that : when evaluating a request, Kong will first try
to match the APIs with the most rules.

Proxying behavior

The proxying rules above detail how Kong forwards incoming requests to your
upstream services. Below we detail what happens internally between the time
Kong recognizes an HTTP request to a target service, and the actual
forwarding of the request upstream.

2. Plugins execution

Kong is extensible via “plugins” that hook themselves in the
request/response lifecycle of the proxied requests. Plugins can perform a
variety of operations in your environment and/or transformations on the proxied
request.

Plugins can be configured to run globally (for all proxied traffic) or on a
per-API basis by creating a plugin configuration
through the Admin API.

When a plugin is configured for a given API, and the API has been matched from
an incoming request, Kong will execute the configured plugin(s) for this
request before proxying it to your upstream service. This includes, among
others, the access phase of the plugin, on which you can find more
information about in the Plugin development guide.

3. Proxying & upstream timeouts

Once Kong has executed all the necessary logic (including plugins), it is ready
to forward the request to your upstream service. This is done via Nginx’s
ngx_http_proxy_module. Since Kong 0.10, the timeout
duration for the connections between Kong and your upstream services may be
configured via these three properties of the API object:

upstream_connect_timeout: defines in milliseconds the timeout for
establishing a connection to your upstream service. Defaults to 60000.

upstream_send_timeout: defines in milliseconds a timeout between two
successive write operations for transmitting a request to your upstream
service. Defaults to 60000.

upstream_read_timeout: defines in milliseconds a timeout between two
successive read operations for receiving a request from your upstream
service. Defaults to 60000.

Kong will send the request over HTTP/1.1, and set the following headers:

Host: <your_upstream_host>, as previously described in this document.

Connection: keep-alive, to allow for reusing the upstream connections.

X-Forwarded-For: <address>, where <address> is the content of
$realip_remote_addr provided by
ngx_http_realip_module appended to the request
header with the same name.

X-Forwarded-Proto: <protocol>, where <protocol> is the protocol used by
the client. In the case where $realip_remote_addr is one of the trusted
addresses, the request header with the same name gets forwarded if provided.
Otherwise, the value of the $scheme variable provided by
ngx_http_core_module will be used.

X-Forwarded-Host: <host>, where <host> is the host name sent by
the client. In the case where $realip_remote_addr is one of the trusted
addresses, the request header with the same name gets forwarded if provided.
Otherwise, the value of the $host variable provided by
ngx_http_core_module will be used.

X-Forwarded-Port: <port>, where <port> is the port of the server which
accepted a request. In the case where $realip_remote_addr is one of the
trusted addresses, the request header with the same name gets forwarded
if provided. Otherwise, the value of the $server_port variable provided by
ngx_http_core_module will be used.

All the other request headers are forwarded as-is by Kong.

One exception to this is made when using the WebSocket protocol. If so, Kong
will set the following headers to allow for upgrading the protocol between the
client and your upstream services:

Connection: Upgrade

Upgrade: websocket

More information on this topic is covered in the
[Proxy WebSocket traffic][proxy-websocket] section.

4. Errors & retries

Whenever an error occurs during proxying, Kong will use the underlying
Nginx retries mechanism to pass the request on to
the next upstream.

There are two configurable elements here:

The number of retries: this can be configured per API using the retries
property of the API object. See the management API for more
details on this.

What exactly constitutes an error: here Kong uses the Nginx defaults, which
means an error or timeout occurring while establishing a connection with the
server, passing a request to it, or reading the response header.

The second option is based on Nginx’s
[proxy_next_upstream][proxy_next_upstream] directive. This option is not
directly configurable through Kong, but can be added using a custom Nginx
configuration. See the configuration reference for
more details.

5. Response

Kong receives the response from the upstream service and send it back to the
downstream client in a streaming fashion. At this point Kong will execute
subsequent plugins added to that particular API that implement a hook in the
header_filter phase.

Once the header_filter phase of all registered plugins has been executed, the
following headers will be added by Kong and the full set of headers be sent to
the client:

Via: kong/x.x.x, where x.x.x is the Kong version in use

X-Kong-Proxy-Latency: <latency>, where latency is the time in milliseconds
between Kong receiving the request from the client and sending the request to
your upstream service.

X-Kong-Upstream-Latency: <latency>, where latency is the time in
milliseconds that Kong was waiting for the first byte of the upstream service
response.

Once the headers are sent to the client, Kong will start executing
registered plugins for that API that implement the body_filter hook. This
hook may be called multiple times, due to the streaming nature of Nginx itself.
Each chunk of the upstream response that is successfully processed by such
body_filter hooks is sent back to the client. You can find more information
about the body_filter hook in the Plugin development
guide.

Configuring a fallback API

As a practical use-case and example of the flexibility offered by Kong’s
proxying capabilities, let’s try to implement a “fallback API”, so that in
order to avoid Kong responding with an HTTP 404, “API not found”, we can
catch such requests and proxy them to a special upstream service of yours, or
apply a plugin to it (such a plugin could, for example, terminate the request
with a different status code or response without proxying the request).

As you can guess, any HTTP request made to Kong would actually match this API,
since all URIs are prefixed by the root character /. As we know from the
[Request URI][proxy-request-uri] section, the longest URIs are evaluated first
by Kong, so the / URI will eventually be evaluated last by Kong, and
effectively provide a “fallback” API, only matched as a last resort.

Configuring SSL for an API

Kong provides a way to dynamically serve SSL certificates on a per-connection
basis. Starting with 0.10, the SSL plugin has been removed and SSL certificates
are directly handled by the core, and configurable via the Admin API. Your
client HTTP library must support the Server Name Indication extension to
make use of this feature.

SSL certificates are handled by two resources of the Kong Admin API:

/certificates, which stores your keys and certificates.

/snis, which associates a registered certificate with a Server Name
Indication.

Proxy WebSocket traffic

Kong supports WebSocket traffic thanks to the underlying Nginx implementation.
When you wish to establish a WebSocket connection between a client and your
upstream services through Kong, you must establish a WebSocket handshake.
This is done via the HTTP Upgrade mechanism. This is what your client request
made to Kong would look like:

WebSocket and TLS

Kong will accept ws and wss connections on its respective http and
https ports. To enforce TLS connections from clients, set the https_only
property of the API to true.

When setting up the API to point to your upstream WebSocket
service, you should carefully pick the protocol you want to use between Kong
and the upstream. If you want to use TLS (wss), then the upstream WebSocket
service must be defined using the https protocol in the API upstream_url
property, and the proper port (usually 443). To connect without TLS (ws),
then the http protocol and port (usually 80) should be used in upstream_url
instead.

If you want Kong to terminate SSL/TLS, you can accept wss only from the
client, but proxy to the upstream service over plain text, or ws.

Conclusion

Through this guide, we hope you gained knowledge of the underlying proxying
mechanism of Kong, from how is a request matched to an API, to how to allow for
using the WebSocket protocol or setup SSL for an API.

This website is Open-Source and can be found at
github.com/Kong/docs.konghq.com.
Feel free to provide feedback to this document there, or propose improvements!

If not already done, we suggest that you also read the
Load balancing Reference, as it closely relates to the
topic we just covered.