Назад | Перейти на главную страницу

nginx try_files, выдающий http перенаправление через балансировщик нагрузки; нужен https

Мой экземпляр nginx находится за балансировщиком нагрузки с завершением SSL, и я хочу, чтобы все URL-адреса попали https конечные точки, что означает http быть перенаправленным на https.

Все хорошо, когда в конце URL есть косая черта. Все они красиво перенаправляются:

#!/bin/sh

do_curl() {
   echo "\n$ do_curl $1"
   curl -L -s -D - "$1" -o /dev/null | grep -iE 'Location|HTTP/|server'
}

$ do_curl https://example.com/
HTTP/2 200

$ do_curl http://example.com/foo/
HTTP/1.1 301 Moved Permanently
Location: https://example.com/foo/
HTTP/2 200

$ do_curl https://example.com/foo/
HTTP/2 200

Но когда те же URL-адреса не имеют завершающей косой черты, nginx try_files похоже, издает http перенаправлять всегда: bad.png

Вот мой nginx vhost.conf:

server {
    listen 80;
    root /app/;
    index index.html index.htm;

    # This 'if' block is only needed because my SSL-terminated Load balancer proxies both http and https to nginx.
    # If my Load balancer only proxied https to nginx, and dropped http, this 'if' block can be omitted.
    if ($http_x_forwarded_proto = "http") {
        return 301 https://$host$request_uri;
    }

    location / {
        try_files $uri $uri/ =404;
    }
}

Как мне получить nginx try_files перенаправить напрямую с https $scheme когда он попадает в $uri/ параметр (2-й параметр в моем try_files выше) и успешно находит соответствующий файл $uri/<index> (где index определяется index директиву в конфигурации nginx выше)?

Я искал похожие вопросы, например Вот, Вот, или Вот но так и не смог найти ничего отдаленно относящегося к делу.

Как отметил @Florin в комментариях к вопросу, try_files выполняет только перезапись. Я вернулся и опустил try_files блок в моем vhost.conf и правда, я вернулся к тому же поведению, когда https URL с без косой черты перенаправить на его http следом аналог.

Решение

Вместо этого заголовок моего вопроса должен был быть больше похож на «Как предотвратить перенаправление nginx с HTTPS на HTTP», что тогда было бы дублирующим вопросом Как предотвратить перенаправление nginx с HTTPS на HTTP на AWS? что @Richard указал в своем комментарии на мой вопрос, и на который он ответил.

По совпадению, мои обстоятельства и вопрос на самом деле идентичны тем, что в этом вопросе. В своем ответе @Richard указывает, что лучший способ смягчить проблему, когда nginx предполагает то же самое $scheme в качестве инициатора запроса (т. е. балансировщика нагрузки с завершенным SSL) будет выполнять замену http с участием https в Location заголовок в точке балансировщика нагрузки, что для меня было невозможно. Затем он продолжает описывать три способы выполнения редиректов, где $scheme было бы https.

Из трех решений, которое сработало для меня, было использование absolute_redirect off;. Это помешало nginx использовать неправильный $scheme что он использовал в редиректах.

Теперь мой vhost.conf просто должно быть:

server {
    listen 80;
    root /app/;
    index index.html index.htm;

    absolute_redirect off;

    # This 'if' block is only needed because my SSL-terminated Load balancer proxies both http and https to nginx.
    # If my Load balancer only proxied https to nginx, and dropped http, this 'if' block can be omitted.
    if ($http_x_forwarded_proto = "http") {
        return 301 https://$host$request_uri;
    }
}