У меня есть следующий код для попытки перенаправить любой трафик http
на эквивалентный https
// Add some redirect logic to ensure that https is always used in production, staging, development environment
app.use((req, res, next) => {
// if NODE_ENV is 'local' don't redirect to https, only do so for our deployed server environments
if (!['development', 'staging', 'production'].includes(process.env.NODE_ENV)) return next()
if (!req.secure) {
return res.redirect(301, `https://${req.headers.host}${req.originalUrl}`)
}
next()
})
/**
* Bootstrap routes
*/
require('./routes')(app)
Однако, когда я иду, чтобы проверить это в браузере и ввожу что-то вроде http://example.com
, я получаю предупреждение в браузере о цикле перенаправления, и в моих журналах papertrail я вижу, что console.info срабатывает много раз снова и снова.
Я пропустил что-то простое здесь? Любая помощь приветствуется.
Почему вы думали, что не увидите его много раз? Если вы хотите войти только при перенаправлении, это не то место. Обратите внимание, что вы можете использовать expressjs.com/en/api.html#req.secure.
@jonrsharpe Думаю, я увижу это не более двух раз, если сделаю запрос на получение http://example.com
. Один раз для первого выполнения, а затем для второго после вызова redirect
. Но если я не буду делать больше запросов, журнал не должен продолжать стрелять вечно.
@jonrsharpe также пробовал с req.secure
, и происходит то же самое. Бесконечный цикл редиректов.
А что происходит, когда https://example.com
загружается? Это всего лишь один простой HTML-файл или он затем делает запросы на таблицы стилей и скрипты?
прямо сейчас я просто возвращаю статический json. Таким образом, после первоначального запроса GET никакие другие запросы не срабатывают.
также изменил мой приведенный выше код еще немного, чтобы сделать его немного чище.
попробуйте добавить :
к имени протокола в req.protocol === 'https:'
.
// Add some redirect logic to ensure that https is always used in production, staging, development environment
app.use((req, res, next) => {
console.info('here')
// if NODE_ENV is 'local' don't redirect to https, only do so for our deployed server environments
if (!['development', 'staging', 'production'].includes(process.env.NODE_ENV)) return next()
// request was via https, so do no special handling
if (req.protocol === 'https:') return next(); // <---- here, add : after https
res.redirect('https://' + req.headers.host + req.url)
})
/**
* Bootstrap routes
*/
require('./routes')(app)
UPD: это потому, что парсер URL возвращает протокол как https:
. Посмотрите эти примеры из режима repl nodejs
$ node
> url.parse('https://ya.ru')
Url {
protocol: 'https:',
slashes: true,
auth: null,
host: 'ya.ru',
port: null,
hostname: 'ya.ru',
hash: null,
search: null,
query: null,
pathname: '/',
path: '/',
href: 'https://ya.ru/'
}
https:
, а не https
, как упоминалось в комментариях
Express не использует url.parse для определения протокола, поэтому этот пример не актуален: github.com/expressjs/express/blob/…. Опять же, мой комментарий заключался в том, что двоеточия там быть не должно.
Наткнулся на этот StackOverflow: В express.js req.protocol не принимает «https» для моей защищенной ссылки. Это всегда фото "http"
Добавление app.enable('trust proxy')
устранило проблему и позволило приведенному выше коду работать. Точно так же я использую Heroku.
А, в примере, которым я поделился, применяется промежуточное ПО: github.com/textbook/starter-kit/blob/…
ну, обычно это работа обратного прокси-сервера, такого как nginx, для перенаправления вашего http на https