Как заставить node.js/express.js использовать HTTPS, когда он работает за балансировщиком нагрузки AWS

Я запускаю узел/экспресс-сервис на AWS и развернул ELB перед ним. Когда я запускаю экземпляр ELB с включенным SSL, он работает для первой страницы, на которую я попал, но затем переключается на HTTP для каждого доступа к серверу после этого.

Правило маршрутизации на ELB завершает SSL и переходит на порт 8080, который прослушивает узел.

Решение для завершения SSL будет отлично работать для моих целей, но как я могу продолжать последующие вызовы серверов на HTTPS?

Ответ 1

Я столкнулся с той же проблемой, но в немного другом контексте. Я развертывал приложение Node.js/Express, используя AWS Elastic Beanstalk, и смог установить на нем SSL-сертификат.

Результатом этого было то, что мое приложение было доступно как по протоколу http, так и по протоколу https. Таблица маршрутизации балансировки нагрузки выглядела так:

(Load balancer) http 80 --> (Node instance) http 8080
(Load balancer) https 443 --> (Node instance) http 8080

Поэтому вопрос состоял в том, чтобы разрешить только https-соединение в моем приложении node.js, но разрешить перенаправление на https, если соединение было выполнено с помощью http.

Поскольку за балансировщиком нагрузки AWS все коммуникации выполняются через http, глобальную команду перенаправления (в этом случае промежуточное ПО), как этот, создается бесконечный цикл перенаправления:

app.use(function(req, res, next) {
    if((!req.secure) && (req.protocol !== 'https')) {
        res.redirect('https://' + req.get('Host') + req.url);
    }
}

→ просто потому, что инструкция (req.protocol !== 'https') всегда будет правдой!

Из этого сообщения в блоге (http://matthew.mceachen.us/blog/howto-force-https-with-amazon-elastic-load-balancer-and-apache-1071.html), оказывается, что AWS ELB добавляет заголовок X-Forwarded-Proto, который вы можете записать, чтобы узнать, какой протокол использовался до балансировки нагрузки (http или https).

Так что эта небольшая модификация сделала трюк:

app.use(function(req, res, next) {
    if((!req.secure) && (req.get('X-Forwarded-Proto') !== 'https')) {
        res.redirect('https://' + req.get('Host') + req.url);
    }
    else
        next();
});

Надеюсь, это поможет!