Конечный слэш Nginx Ingress Controller с перенаправлением HTTPS
Конечный слэш Nginx Ingress Controller с перенаправлением HTTPS
Я пытаюсь перенаправить запросы с HTTP на HTTPS, используя Ingress с Nginx Ingress Controller. Мое приложение написано на Django v3.0.7, мой контроллер Nginx - v0.46.0 и k8s v1.19.8.
У меня такой вход:
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
Запросы на
https://.../api/v1/get-token/
, вызовите эту ошибку:
[05/May/2021:20:39:49 +0000] "POST /api/v1/get-token// HTTP/1.1" 404
=> POST получить дополнительную информацию в конце. Но тот же запрос с HTTP или
https://.../api/v1/get-token
(без трейлинга) в порядке.
Если я удалю
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /api/v1/$1/
Перенаправление удаляет трейлинг и заставляет POST превращаться в GET во всех запросах HTTP POST, вызывая 403 - Метод не разрешен, как показано в журналах Nginx:
[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
но запрос HTTP POST отлично работает с
http://.../api/v1/get-token//
(два замыкающих).
Есть ли способ решить эту проблему? Редирект 308 HTTP -> HTTPS важен, поэтому я не могу его удалить, но есть ли способ заставить запросы иметь один и только один конечный
/
? Спасибо.
1 ответ
Здесь есть две проблемы
Проблема #1
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /api/v1/$1/
вызывает запросы, отправленные на
https://.../api/v1/get-token/
чтобы закончить HTTP 404 Not Found, но работает нормально.
Почему?
Поскольку трейлинг в конце
nginx.ingress.kubernetes.io/rewrite-target: /api/v1/$1/
перезапись добавляется к URL-адресу, и
/api/v1/get-token//
ведет к несуществующему ресурсу.
Что с этим делать?
Изменять
path
ключ к
/api/v1/?(.*\b)/
. Я не уверен на 100%, что это сработает, но попробовать стоит.
или
Удалить трейлинг
/
от переписать.
Теперь это вызывает проблему №2.
Проблема # 2
Запросы к
https://.../api/v1/get-token
заканчивается на 405 Метод запрещен .
Почему?
Первое перенаправление работает нормально (HTTP 308), однако запрос снова перенаправляется с помощью HTTP 301.
В статье MDN о HTTP 301 говорится:
Даже если спецификация требует, чтобы метод (и тело) не изменялся при выполнении перенаправления, не все пользовательские агенты согласуются с ним - вы все равно можете найти этот тип программного обеспечения с ошибками. Поэтому рекомендуется использовать код 301 только в качестве ответа для методов GET или HEAD и вместо этого использовать постоянное перенаправление 308 для методов POST, поскольку изменение метода явно запрещено с этим статусом.
В основном HTTP 301 вызывает
POST
стать, и
GET
не разрешено, следовательно, HTTP 405.
Что с этим делать?
Не перенаправляйте запросы дважды, особенно с HTTP 301.