Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Routes entity page, router expressions, proxying #168

Merged
merged 38 commits into from
Jan 10, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
2d0e1ab
Start revising routes entity page
cloudjumpercat Dec 10, 2024
2804553
Continue revising routes entity, start drafting the rewrite URLs how to
cloudjumpercat Dec 10, 2024
9a845e9
Fix vale spelling error
cloudjumpercat Dec 11, 2024
117daae
Capitalize entities
cloudjumpercat Dec 11, 2024
c3c8da6
Revise how to after testing
cloudjumpercat Dec 11, 2024
ccbd48e
Plan out routing section for matching and priority section split
cloudjumpercat Dec 11, 2024
e9b3935
Apply suggestions from code review
cloudjumpercat Dec 12, 2024
5a74da6
Edit routes, upstream, add proxy page, update source file with doc links
cloudjumpercat Dec 12, 2024
2bd7119
Merge branch 'main' into routes-entity
cloudjumpercat Dec 13, 2024
89adbb6
Fix broken breadcrumb link
cloudjumpercat Dec 13, 2024
45b8d04
Revise a whole bunch of pages
cloudjumpercat Dec 13, 2024
5cf9492
Revise proxy reference and routing
cloudjumpercat Dec 16, 2024
6c175ce
Start adding the needed expressions router pages
cloudjumpercat Dec 16, 2024
3aefeb7
Add drafts of all expressions docs
cloudjumpercat Dec 17, 2024
3336680
Finish expressions router concept page
cloudjumpercat Dec 18, 2024
1f69366
Remove expressions router how to and move enabling info to other pages
cloudjumpercat Dec 18, 2024
7165bbc
Apply suggestions from code review
cloudjumpercat Dec 18, 2024
81e2355
Apply Angel's remaining feedback to the rewrite urls how to
cloudjumpercat Dec 18, 2024
34e2faa
Apply suggestions from code review
cloudjumpercat Dec 18, 2024
586509d
Apply Lena's feedback to Upstream entity page
cloudjumpercat Dec 18, 2024
e819205
Revise Routes entity based on feedback
cloudjumpercat Dec 18, 2024
1a1733d
Revise proxy reference
cloudjumpercat Dec 19, 2024
990afc6
Minor link fixes, make vale happy again
cloudjumpercat Dec 19, 2024
fc92c6f
Fix broken links
cloudjumpercat Dec 19, 2024
c5eb4b1
Remove upstream and target entity pages since they are now handled in…
cloudjumpercat Dec 19, 2024
318b8d6
Convert expressions router image to mermaid
cloudjumpercat Dec 19, 2024
4300032
Merge branch 'main' into routes-entity
cloudjumpercat Dec 19, 2024
1def049
Apply remaining feedback
cloudjumpercat Dec 19, 2024
5d27dfe
Add proxying ref placeholder page with todo
cloudjumpercat Jan 6, 2025
6adb293
Merge branch 'main' into routes-entity
lena-larionova Jan 8, 2025
3d090cf
Apply suggestions from code review
cloudjumpercat Jan 10, 2025
847bb93
Apply remaining feedback
cloudjumpercat Jan 10, 2025
5f9074c
Merge branch 'main' into routes-entity
cloudjumpercat Jan 10, 2025
e0b7bc2
Apply new feature table formatting
cloudjumpercat Jan 10, 2025
d03b20d
Fix feature table formatting
cloudjumpercat Jan 10, 2025
e6e72cf
Apply suggestions from code review
lena-larionova Jan 10, 2025
446ab46
fix centering issue in feature tables
lena-larionova Jan 10, 2025
d9cc8f6
fix faqs key
lena-larionova Jan 10, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
175 changes: 147 additions & 28 deletions app/_gateway_entities/route.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,57 +4,176 @@ content_type: reference
entities:
- route

description: A route is a path to a resource within an upstream application.
description: |
A Route is a path which defines how (and if) requests are passed to Gateway Services and their respective upstream applications based on a set of configured rules.

related_resources:
- text: Services
- text: Gateway Service entity
url: /gateway/entities/service/
- text: Routing in {{site.base_gateway}}
url: /gateway/routing/
- text: Expressions router
url: /gateway/routing/expressions/
- text: Upstream entity
url: /gateway/entities/upstream/

tools:
- admin-api
- konnect-api
- kic
- deck
- terraform
- admin-api
- konnect-api
- kic
- deck
- terraform

schema:
api: gateway/admin-ee
path: /schemas/Route
api: gateway/admin-ee
path: /schemas/Route

faqs:
- q: How can I divert traffic from an old URL to a new one with {{site.base_gateway}}?
a: Create a new route and point it to the existing Gateway Service. The new route will proxy traffic to the existing service at the new URL.

---

## What is a route?
## What is a Route?

A Route is a path to a resource within an upstream application. In {{site.base_gateway}}, Routes typically map to endpoints exposed through [Gateway Services](/gateway/entities/service/). Routes determine how (and if) requests are sent to their Services after they reach {{site.base_gateway}}. Where a Service represents the backend API, a Route defines what is exposed to clients.

Routes can also define rules that match requests to associated Services. Because of this, one Route can reference multiple endpoints. Once a Route is matched, {{site.base_gateway}} proxies the request to its associated Service. A basic Route should have a name, path or paths, and reference an existing Service.

{% mermaid %}
cloudjumpercat marked this conversation as resolved.
Show resolved Hide resolved
lena-larionova marked this conversation as resolved.
Show resolved Hide resolved
flowchart LR
A(API client)
B("`Route
(/mock)`")
C("`Gateway Service
(example-service)`")
D(Upstream
application)

A <--requests
responses--> B
subgraph id1 ["`
**KONG GATEWAY**`"]
B <--requests
responses--> C
end
C <--requests
responses--> D

style id1 rx:10,ry:10

{% endmermaid %}

## Route and Service interaction

Routes, in conjunction with [Services](/gateway/entities/service/), let you expose your Services to applications with {{site.base_gateway}}. {{site.base_gateway}} abstracts the Service from the applications by using Routes. Since the application always uses the Route to make a request, changes to the Services, like versioning, don’t impact how applications make the request. Routes also allow the same Service to be used by multiple applications and apply different policies based on the Route used.

For example, say you have an external application and an internal application that need to access the `example_service` Service, but the *external* application should be limited in how often it can query the Service to avoid a denial of service. If you apply a rate limit policy to the Service and the *internal* application calls it, the internal application is also limited. Routes can solve this problem.

In this example, you can create two Routes to handle the two applications, say `/external` and `/internal`, and point both of them to `example_service`.
You can configure a policy to limit how often the `/external` Route is used.
When the external application tries to access the Service via {{site.base_gateway}} using `/external`, it's rate limited.
But when the internal application accesses the Service using {{site.base_gateway}} using `/internal`, the internal application isn't limited.

The following diagram illustrates this example:

{% mermaid %}
flowchart LR
A(External application)
B("`Route (/external)`")
B2(Rate Limiting
plugin)
C("`Service (example-service)`")
D(Upstream application)
E(Internal application)
F("`Route (/internal)`")

A --request--> B
E --request--> F

subgraph id1 ["`
**KONG GATEWAY**`"]
B --> B2 --"10 requests
per minute"--> C
F ---> C
end

C --transformed
and routed
requests--> D

style id1 rx:10,ry:10

{% endmermaid %}

## Route use cases

Common use cases for Routes:

| Use Case | Description |
|--------|----------|
| Rate limiting | Use Routes to set different rate limits for clients accessing the upstream application via specific paths, for example `/internal` or `/external`. <br><br>[Enable a rate limiting plugin on Routes attached to the Service](/plugins/rate-limiting-advanced/) |
| Perform a simple URL rewrite | Use the Routes entity to rename an endpoint. For example, you can rename your legacy `/api/old/` upstream endpoint to a publicly accessible API endpoint named `/new/api`. |
| Perform a complex URL rewrite | Use the Routes entity to rewrite a group of paths, such as replacing `/api/<function>/old` with `/new/api/<function>`. <br><br> [Request Transformer Advanced plugin](/plugins/request-transformer-advanced/) |
| Describe paths as patterns using regular expressions | [Expressions router](/gateway/routing/expressions/) |

## How routing works

For each incoming request, {{site.base_gateway}} must determine which Service gets to handle it based on the Routes that are defined. As soon as a Route yields a match, the router stops matching and {{site.base_gateway}} uses the matched Route to [proxy the current request](/gateway/traffic-control/proxying/).

If multiple Routes match, {{site.base_gateway}} handles routing in the following order:

1. {{site.base_gateway}} finds Routes that match the request by comparing the defined routing attributes with the attributes in the request.
1. If multiple Routes match, the {{site.base_gateway}} router then orders all defined Routes by their [priority](#priority-matching) and uses the highest priority matching Route to handle a request.

{{site.base_gateway}} provides two different routers, enabled via the `router_flavor` property in `kong.conf`. The router you should use depends on your use case and {{site.base_gateway}} version:
* **[Expressions router](/gateway/routing/expressions/):** The recommended method for anyone running {{site.base_gateway}} 3.4.x or later. Can be run in both `traditional_compat` and `expressions` modes. Handles complex routing logic and regex in Routes.
* **Traditional compatibility router:** Only recommended for anyone running {{site.base_gateway}} 2.9.x or earlier. The default routing method for {{site.base_gateway}}. Doesn't handle complex routing logic.

### Path matching

Keep the following path matching criteria in mind when configuring paths:

* **Regex in paths:** For a path to be considered a regular expression, it must be prefixed with a `~`. You can avoid creating complex regular expressions using the [Router Expressions language](/gateway/routing/expressions/).
* **Capturing groups:** [Regex capture groups](/gateway/routing/expressions/#example-expressions) are also supported, and the matched group will be extracted from the path and available for plugins consumption.
* **Escaping special characters:** When configuring Routes with regex paths via the Admin API, be sure to URL encode your payload if necessary according to [RFC 3986](https://tools.ietf.org/html/rfc3986).
* **Normalization behavior:** To prevent trivial Route match bypass, the incoming request URI from client
is always normalized according to [RFC 3986](https://tools.ietf.org/html/rfc3986)
before router matching occurs.

Regex Route paths only use methods 1 and 2. In addition, if the decoded character becomes a regex meta character, it will be escaped with backslash.

{{page.description | liquify}} Services can store collections of objects like plugin configurations, and policies, and they can be associated with routes. In {{site.base_gateway}}, routes typically map to endpoints that are exposed through the {{site.base_gateway}} application. Routes can also define rules that match requests to associated services. Because of this, one route can reference multiple endpoints. A basic route should have a name, path or paths, and reference an existing service.
### Priority matching

You can also configure routes with:
If multiple Routes match, the {{site.base_gateway}} router then orders all defined Routes by their priority and uses the highest priority matching Route to handle a request. How Routes are prioritized depends on the router mode you're using.

* Protocols: The protocol used to communicate with the upstream application.
* Hosts: Lists of domains that match a route
* Methods: HTTP methods that match a route
* Headers: Lists of values that are expected in the header of a request
* Redirect status codes: HTTPS status codes
* Tags: Optional set of strings to group routes with
#### Traditional compatibility mode

## Route and service interaction
In `traditional_compat` mode, the priority of a Route is determined as
follows, by the order of descending significance:

Routes, in conjunction with [services](/gateway/entities/service/), let you expose your services to applications with {{site.base_gateway}}. {{site.base_gateway}} abstracts the service from the applications by using routes. Since the application always uses the route to make a request, changes to the services, like versioning, don’t impact how applications make the request. Routes also allow the same service to be used by multiple applications and apply different policies based on the route used.
1. **Priority points:** A priority point is added for every `methods`, `host`, `headers`, and `snis` value that a Route has. Routes with higher priority point values will be considered before those with lower values.
2. **Wildcard hosts:** Among Routes with the same priority point value, Routes without a wildcard host specified (or no host at all) are prioritized before those that have any wildcard host specification.
3. **Header count:** The resulting groups are sorted so the Routes with a higher number of specified headers have higher priority than those with a lower number of headers.
4. **Regular expressions and prefix paths:** Routes that have a regular expression path are considered first and are ordered by their `regex_priority` value. Routes that have no regular expression path are ordered by the length of their paths.
5. **Creation date:** If all of the above are equal, the router chooses the Route that was created first using the Route's `created_at` value.

For example, if you have an external application and an internal application that need to access the `example_service` service, but the external application should be limited in how often it can query the service to assure no denial of service. If a rate limit policy is configured for the service when the internal application calls the service, the internal application is limited as well. Routes can solve this problem.
When two Routes have the same path, {{site.base_gateway}} uses a tiebreaker. For example, if the rule count for the given request is the same for both Routes `A` and `B`, then the following tiebreaker rules are applied in the order they are listed. Route `A` will be selected over `B` if:
* `A` has only plain Host headers and `B` has one or more wildcard
host headers
* `A` has more non-Host headers than `B`
* `A` has at least one regex path and `B` has only plain paths
* `A`'s longest path is longer than `B`'s longest path
* `A.created_at < B.created_at`

In the example above, two routes can be created, say /external and /internal, and both routes can point to `example_service`. A policy can be configured to limit how often the /external route is used and the route can be communicated to the external client for use. When the external client tries to access the service via {{site.base_gateway}} using /external, they are rate limited. But when the internal client accesses the service using {{site.base_gateway}} using /internal, the internal client will not be limited.
#### Expressions router mode

## Dynamically rewrite request URLs with routes
In [`expressions` mode](/gateway/routing/expressions/), when a request comes in, {{site.base_gateway}} evaluates Routes with a higher `priority` number first. The priority is a positive integer that defines the order of evaluation of the router. The larger the priority integer, the sooner a Route will be evaluated. In the case of duplicate priority values between two Routes in the same router, their order of evaluation is undefined.

Routes can be configured dynamically to rewrite the requested URL to a different URL for the upstream. For example, your legacy upstream endpoint may have a base URI like `/api/old/`. However, you want your publicly accessible API endpoint to now be named `/new/api`. To route the service's upstream endpoint to the new URL, you could set up a service with the path `/api/old/` and a route with the path `/new/api`.
### Routing performance recommendations

{{site.base_gateway}} can also handle more complex URL rewriting cases by using regular expression capture groups in the route path and the [Request Transformer Advanced](/plugins/request-transformer-advanced/) plugin. For example, this can be used when you must replace `/api/<function>/old` with `/new/api/<function>`.
You can use the following recommendations to increase routing performance:

{{site.base_gateway}} 3.0.x or later ships with a new router. The new router can use regex expression capture groups to describe routes using a domain-specific language called Expressions. Expressions can describe routes or paths as patterns using regular expressions. For more information about how to configure the router using Expressions, see [How to configure routes using expressions](https://docs.konghq.com/gateway/latest/key-concepts/routes/expressions/).
* In `expressions` mode, we recommend putting more likely matched Routes before (as in, higher priority) those that are less frequently matched.
* Regular expressions in Routes use more resources to evaluate than simple prefixes. In installations with thousands of Routes, replacing a regular expression with simple prefix can improve throughput and latency of {{site.base_gateway}}. If a regex must be used because an exact path match must be performed, using the [expressions router](/gateway/routing/expressions/) will significantly improve {{site.base_gateway}}’s performance in this case.

## Schema

Expand Down
4 changes: 2 additions & 2 deletions app/_includes/components/feature_table.html
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,13 @@
</td>
{% for column in include.columns %}
{% assign v = row[column.key] %}
<td class="text-center">
<td{% if v == true or v == false %} class="text-center"{% endif %}>
{% if v == true %}
{% include icon_true.html %}
{% elsif v == false %}
{% include icon_false.html %}
{% else %}
{{v}}
{{v | liquify | markdown}}
{% endif %}
</td>
{% endfor %}
Expand Down
4 changes: 4 additions & 0 deletions app/_includes/info_box/concept.html
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,8 @@

{% if page.related_resources %}
{% include info_box/sections/related_resources.html %}
{% endif %}

{% if page.min_version %}
{% include info_box/sections/min_version.html min_version=page.min_version %}
{% endif %}
Loading
Loading