Make links in response relative to new path

4/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
kubernetes
nginx
nginx-ingress

2 Answers

5/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

5/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