Nginx Ingress Controller trailling slash with HTTPS redirect
I'm trying to redirect requests from HTTP to HTTPS using an Ingress with Nginx Ingress Controller. My app is written in Django v3.0.7, my Nginx Controller is v0.46.0 and k8s v1.19.8.
I have the following ingress:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: INGRESS-NAME
namespace: INGRESS-NS
annotations:
kubernetes.io/ingress.class: "nginx"
nginx.ingress.kubernetes.io/use-regex: "true"
nginx.ingress.kubernetes.io/ssl-redirect: "true"
nginx.ingress.kubernetes.io/rewrite-target: /api/v1/$1/
cert-manager.io/cluster-issuer: "ISSUER-NAME"
nginx.ingress.kubernetes.io/permanent-redirect-code: '308'
spec:
tls:
...
rules:
- host: MY-DOMAIN
http:
paths:
- path: /api/v1/?(.*)
pathType: Prefix
backend:
service:
name: SVC-NAME
port:
number: SVC-PORT
Requests at https://.../api/v1/get-token/
, raise this error:
[05/May/2021:20:39:49 +0000] "POST /api/v1/get-token// HTTP/1.1" 404
=> POST get an extra /
at the end. But the same request with HTTP or https://.../api/v1/get-token
(no trailing /
) is fine.
If I remove the
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /api/v1/$1/
The redirect removes trailing /
and it causes POST to turn into GET in all HTTP POST request causing an 403 - Method not allowed as shown in Nginx Logs:
[05/May/2021:20:54:52 +0000] "POST /api/v1/get-token HTTP/1.1" 308 164
[05/May/2021:20:54:53 +0000] "POST /api/v1/get-token HTTP/1.1" 301 0
[05/May/2021:20:54:53 +0000] "GET /api/v1/get-token/ HTTP/1.1" 405
but HTTP POST request works fine with http://.../api/v1/get-token//
(two trailing /
).
Is there a way to solve this problem? The 308 HTTP -> HTTPS redirect is important, so I can't remove it, but is there a way to force requests to have one, and only one, trailing /
? Thanks.
There are two problems here
Problem #1
causes requests sent to
https://.../api/v1/get-token/
to end with HTTP 404 Not Found, buthttps://.../api/v1/get-token
woks fine.Why?
Because trailing
/
at the end ofnginx.ingress.kubernetes.io/rewrite-target: /api/v1/$1/
rewrite is added to the URL, and/api/v1/get-token//
leads to a resource that does not exist.What to do about it?
Change
path
key to/api/v1/?(.*\b)/
. I'm not 100% sure it will work, but it's worth a try.or
Remove trailing
/
from rewrite.Now, doing that causes problem #2.
Problem #2
Requests to
https://.../api/v1/get-token
ends with 405 Method Not Allowed.Why?
First redirection works fine (HTTP 308), however request is redirected again with HTTP 301.
MDN article on HTTP 301 states:
Basically HTTP 301 causes
POST
to becomeGET
, andGET
is not allowed, hence HTTP 405.What to do about it?
Make sure not to redirect requests twice, especially with HTTP 301.