I'm setting up simple Kubernetes cluster using GKE. I've set up Java Spring boot app as Kubernetes Deployment and Service (with type Load Balancer
, exposed on port 80
). This app is working perfectly fine when accessed directly using external IP for the service.
I've also installed nginx-ingress for GKE and provided following Ingress resource:
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
annotations:
kubernetes.io/ingress.class: "nginx"
nginx.ingress.kubernetes.io/enable-rewrite-log: "true"
nginx.ingress.kubernetes.io/rewrite-target: /$1
name: rewrite
namespace: default
spec:
rules:
- host: "myhost.ddns.net"
http:
paths:
- backend:
serviceName: app-java
servicePort: 80
path: /app-java/?(.*)
From now on, funny things occur:
Problem 1: if I access site at http://myhost.ddns.net/app-java
- I get only HTML file, all other resources have 404
(download attempt from http://myhost.ddns.net/foo.js
instead of http://myhost.ddns.net/app-java/foo.js
.
Problem 2: If I access site at http://myhost.ddns.net/app-java/
- I get both HTML file and all scripts and images. However, when I dig deeper, sending form content via POST fails. It's HTML code is:
<form action="/select" method="post">
Which tries to access http://myhost.ddns.net/select
instead of http://myhost.ddns.net/app-java/select
.
I found out that it might me strongly connected to this question: Thymeleaf template (in Spring boot application) behind reverse proxy not forming url's correctly. SOlution provided there is to write following nginx reverse proxy configuration:
location /app-java {
proxy_pass http://10.0.0.0:80;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host $host:$server_port;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Prefix /app-java;
}
However, I have no idea how to translate it to ingress resource yaml.
How can I fix this url-rewrite problem using ingress?
Edit: After hints from @HelloWorld I've reorganized application to serve content on /app-java
context path (using Spring Boot 2 property server.servlet.context-path=/app-java
). After that, I've changed rewrite-target
to:
nginx.ingress.kubernetes.io/rewrite-target: /app-java/$1
And now it's working fine.
I see you are trying to make your browser to add a prefix to all paths in flight.
I believe you must have misunderstood the idea of X-Forwarded-Prefix
and whatever was described in Thymeleaf template (in Spring boot application) behind reverse proxy not forming url's correctly, where community member described how to pass this header to your application. If you want to try it and see how it works you can achieve this by simply adding this annotation to your ingress object:
nginx.ingress.kubernetes.io/x-forwarded-prefix: "/app-java"
but notice this is not going to solve your problem.
Of course you can also add these headers to the response from application so that they get sent to your browser (what I believe you were expecting to achieve) but browsers don't care about these headers so there is no point in doing it.
If you still want to try it yourself and prove it, you can add this annotation to the ingress object:
nginx.ingress.kubernetes.io/configuration-snippet: |
more_set_headers "X-Forwarded-Prefix: /app-java";
The only way as far as I know to solve this issue is to modify your application code so that it's responding with correct paths.
You can find that many applications use customizable base path, configurable either by env variables, config files or by cli arguments.