简体   繁体   中英

Nginx Ingress Controller trailling slash with HTTPS redirect

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

annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /api/v1/$1/

causes requests sent to https://.../api/v1/get-token/ to end with HTTP 404 Not Found , but https://.../api/v1/get-token woks fine.

Why?
Because trailing / at the end of nginx.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:

Even if the specification requires the method (and the body) not to be altered when the redirection is performed, not all user-agents align with it - you can still find this type of bugged software out there. It is therefore recommended to use the 301 code only as a response for GET or HEAD methods and to use the 308 Permanent Redirect for POST methods instead, as the method change is explicitly prohibited with this status.

Basically HTTP 301 causes POST to become GET , and GET is not allowed, hence HTTP 405 .

What to do about it?
Make sure not to redirect requests twice, especially with HTTP 301 .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM