Переадресация HTTPS работает только при перезагрузке страницы

Я установил SSL-сертификат на своей странице, который запускает приложение Node.js + Express, настроил сервер Express всегда на перенаправление на HTTP-сервер, и все работает нормально, за исключением того, что перенаправление https работает только тогда, когда страница перезагружается или когда клавиша Enter снова нажата. Я записал gif, чтобы показать, что происходит:

http://recordit.co/uBiW3bcQCM

И вот моя экспресс-конфигурация.

var express = require('express');
var path = require('path');
var serveStatic = require('serve-static');

var forceSsl = function (req, res, next) {
  if (req.headers['x-forwarded-proto'] !== 'https') {
    return res.redirect(['https://', req.get('Host'), req.url].join(''));
  }
  return next();
};

app = express();
app.use(serveStatic(__dirname));

if(process.env.NODE_ENV === 'production') {
  app.use(forceSsl);
}

app.all('/*', function(req, res) {
  res.sendfile('index.html');
});

var port = process.env.PORT || 5000;
app.listen(port);

console.log('server started '+ port);

Мое приложение работает на Heroku. Может ли кто-нибудь помочь мне узнать, что происходит?

Спасибо заранее.

Ответ 1

Я думаю, что ваш сервер отправляет контент перед отправкой заголовков перенаправления.

Если вы меняете:

app.use(serveStatic(__dirname));
app.use(forceSsl);

для

app.use(forceSsl);
app.use(serveStatic(__dirname));

Кажется, он работает намного лучше!

Причина, по которой ваш браузер выполнял перенаправление при перезагрузке/вводе, неясен для меня, поскольку я не мог воспроизвести поведение. В FF я никогда не перенаправлялся.

Возможно, это связано с тем, что заголовки запроса различаются, например HEAD, вместо GET или что-то еще. Я не мог больше исследовать это, использовать Wireshark или Burpsuite, чтобы точно знать, что происходит, если это все еще имеет значение...

Ответ 2

Это redirectToHTTPS() промежуточное программное обеспечение должно работать на вас. Он перенаправляется на сайт https, даже если пользователь не предоставляет префикс. Добавьте X-Forwarded-Port для идентификации порта, используемого для сайта https.

function redirectToHTTPS () {
  return function middlewareRedirectToHTTPS (req, res, next) {
    const isNotSecure = (!req.get('x-forwarded-port') && req.protocol !== 'https') ||
      parseInt(req.get('x-forwarded-port'), 10) !== 443
    if (isNotSecure) {
      return res.redirect('https://' + req.get('host') + req.url)
    }
    next()
}
}