K
Q

Make links in response relative to new path

April 17, 2019

How do I redirect all my

hrefs
within my response to hit my new path. For e.g., my ingress file is

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: ingress-odin
  annotations:    
    nginx.ingress.kubernetes.io/rewrite-target: /$1

spec:
  rules:
  - http:
      paths:
      - path: /odin/?(.*)
        backend:
          serviceName: flask-app-tutorial
          servicePort: 8080

When I visit the page at https://mysite/odin. It works and returns back the response:

The HTML response is:

<html>
..
    <body>
        <div>
            <a href="/v0/index">Home</a>
            <a href="/v0/login">Login</a>
        </div>
       
    </body>
</html>

However, as you can see, the relative links are like

<a href="/v0/index">Home</a>
. If I click on that, it won't work since there is no link like
http://mysite/v0/index
. If I click on the link, I want it to go to
http://mysite/odin/v0/index
. Is it possible either by modifying the links in the response to have
odin
or if I do click on it, it looks at the source url i.e.
http://mysite/odin
and direct it relative to that?

Nginx Version: 1.15.10
ingress-nginx: 0.24.0

So far,I have tried the following.

nginx.ingress.kubernetes.io/configuration-snippet: |
  proxy_set_header Accept-Encoding ""; #disable compression
  sub_filter '<head>' '<head> <base href="/odin/">';


nginx.ingress.kubernetes.io/add-base-url: ":true"
nginx.ingress.kubernetes.io/app-root: /odin

nginx.ingress.kubernetes.io/use-regex: "true"

I have also tried this i.e.

 change the spec.rules.host.paths.path from /odin/?(.*) to/(odin/.*)

There may be a typo in the advice above. I think it should

http
instead of
host
.

-- RAbraham
nginx
kubernetes
nginx-ingress

2 Answers

May 2, 2019

I had a similar problem and inspired by your question I found a solution which worked for me. Your annotation should work like this:

nginx.ingress.kubernetes.io/configuration-snippet: |
  sub_filter_once on;
  sub_filter '<base href="/"' '<base href="/odin/"';

As you see sub_filter is now enabled and I used base instead of head.

-- Alexander Kauerz
Source: StackOverflow

May 7, 2019

Even if you fix the the

sub_filter
configuration snippet by including
sub_filter_once on;
as suggested in the other answer it will not work, because the
base
tag works only with relative paths (see: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/base).

The

app-root
solution is technically correct, but boils down to the same thing as
<base href=... />
, and thus also will fail for
href
tags with a leading slash.

I can see two possibilities:

  1. You can fix all your

    href
    tags, removing leading slashes. If you do that both solutions should work.

  2. You can try to change your location rule to

    - path: /(odin)?/?(.*)
    and the rewrite annotation to:
    nginx.ingress.kubernetes.io/rewrite-target: /$2
    (not forgetting to include the
    nginx.ingress.kubernetes.io/use-regex: "true"
    annotation as well) and it will work with a leading slash as well.

It looks fragile though, as the rule will now match (almost) anything and you loose the possibility to fan out with NGINX with different path prefixes.

A modification of "2)" to make it a more viable alternative would be to match the

/v0
prefix if it's consistent among
href
tags, instead of basically anything.

-- BartoszKP
Source: StackOverflow