Kong ingress - Rewrite path on ingress

Hi,

I was wondering if there was a way, using the kong ingress controller in kubernetes, of rewriting the path of a request at the ingress level.

I saw that you can use the “route.proxy” in the KongIngress object to change the path of a request, for example:

example.com/foo -> example.com/bar

But that only works when the KongIngress is attached to a service.

In my case, i have multiple Ingresses that have the same Service as a backend, and i’m trying to rewrite the path on each ingress to another path:

  • Ingress 1: /foo -> service/bar
  • Ingress 2: /somepath -> service/anotherpath

I tried using the url-rewrite plugin but couldn’t make it work.

Is there some feature or plugin that i’m missing, or there is no support to do this?

Thanks!

(Extra info:
I am using Kong version 1.3.0 in DBless mode, and Kong ingress controller version 0.5.0)

You can use Request Transformer | Kong Docs to accomplish this. There is an undocumented property config.replace.uri where you can set the rewrite rule.

I had the exact same question earlier today:

Unfortunately it does not seem to take uri captures into account so the request-transformer plugin can only do static replacement of uris

EDIT: After further investigation this is possible. The following manifests does the trick of having multiple routes to one service with the path rewritten

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: docs
  annotations:
    plugins.konghq.com: apidocs-rewrite
    kubernetes.io/ingress.class: "kong"
spec:
  rules:
  - http:
      paths:
      - path: /api-docs/demo/(.*)
        backend:
          serviceName: demo-service
          servicePort: http
apiVersion: configuration.konghq.com/v1
kind: KongPlugin
metadata:
  name: apidocs-rewrite
config:
  replace:
    uri: "/api-docs/$(uri_captures[1])"
plugin: request-transformer
1 Like

Thank you for the response!

I will try using the request-transformer plugin then

Hey @goober, thanks for the post. Do you mind enlightening me on where you found the documentation surrounding that uri_captures[1] bit?

I have been struggling through how to get a rewrite to work after getting regular ingress rules to work.

Hi @thatbenguy. Unfortunately, I did not found any documentation for this at all. I had to dig into the source code of the request-transformer-plugin. The README states that the plugin accepts a config.replace.uri parameter, however that information is missing on kong hub

Then I found several examples in the plugin’s test files where the uri_captures were referenced so I decided to try and it succeeded.

If you have trouble getting it to work, please reach out and I can see if I can help you

Ahhhh, I see, that’s why I didn’t find it :slight_smile:

The ‘uri_captures’ is mentioned on the request-transformer-advanced-plugin which is for the enterprise kong version (https://docs.konghq.com/hub/kong-inc/request-transformer-advanced/0.33-x.html#template-as-value). It didn’t sound like you are using enterprise though?

For the moment I just added a bunch of ingress entries for each endpoint I wanted instead of using wildcards and thus requiring the uri_captures. It’s not the cleanest solution, but for now it works.

Thanks for the reply!

UPDATE: With a bit more fiddling i was able to get it working using the uri_captures as you mentioned in your posts. THANKS!
-Ben

@goober

Kubernetes: v1.20.5
Kong: v2.3.4
Kong-Ingress-Controller: v1.1

We have a two services (say A and B) running in their own namespace in K8s cluster and they understand these end-point /v2/A and /v2/B.

But, we have a situation where we have URI as /api/v2/A and /api/v2/B and we want to slice-off /api from the URI and send request to the upstream in the format as they understand /v2/A and /v2/B.

For this, we are using Request-Transformer plugin and we enabled the plugin Cluster-wide (globally and route wise per namespace) as shown below:

Cluster wide:

apiVersion: configuration.konghq.com/v1
kind: KongClusterPlugin
metadata:
name: demo-request-transformer
annotations:
kubernetes.io/ingress.class: kong
labels:
global: ‘true’
config:
replace:
uri: ‘/$(uri_captures[1])’
plugin: request-transformer

Route wide:

apiVersion: configuration.konghq.com/v1
kind: KongPlugin
metadata:
name: demo-request-transformer
annotations:
kubernetes.io/ingress.class: kong
config:
replace:
uri: ‘/$(uri_captures[1])’
plugin: request-transformer

When I try this:
curl -I http://KONG_PROXY_IP:PORT/api/v2/A -----> It redirects to service A and we get 200 OK

But, when I try this:
curl -I http://KONG_PROXY_IP:PORT/api/v2/B -----> It throw 404 Not Found and error log appears on service A. I double-checked that the Ingress route points to correct service.

When I try this:
curl -I http://KONG_PROXY_IP:PORT/v2/B -----> It redirects to service B and we get 200 OK (we have another Ingres rule for /v2/B)

Here plugin only works for service A and throws “404 Not Found” for serviceB end-point. Means at one time, plugin works for one service.

I am not able to understand why it is happening.

Also please educate me what is the actual meaning of uri_captures[1] here in our case?

For some weird reason I was not able to post my Ingress YAML:
Here it is:

Service A:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: demo-ingress-api
namespace: serviceA
annotations:
kubernetes.io/ingress.class: kong
konghq.com/plugins: demo-request-transformer
spec:
rules:

  • host:
    http:
    paths:
    • path: /api/(.*)
      backend:
      serviceName: A-service
      servicePort: 8000

Service B:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: demo-ingress-api
namespace: serviceB
annotations:
kubernetes.io/ingress.class: kong
konghq.com/plugins: demo-request-transformer
spec:
rules:

  • host:
    http:
    paths:
    • path: /api/(.*)
      backend:
      serviceName: B-service
      servicePort: 8000
1 Like