Узел.JS, Express и Heroku - как обрабатывать HTTP и HTTPS?

У меня есть приложение, которое является вполне нормальным Экспресс-приложением-простая логика сервера, представления, много клиентских JS. Мне нужно сделать много запросов AJAX. Некоторые из них должны быть защищены протоколом HTTPS (некоторые не должны).

Итак, мой сервер должен работать как с HTTP, так и с HTTPS. Он также должен работать как на локальной машине (обычно работает с nodemon), так и на Heroku.

насколько я понял, Heroku дает вам один порт (процесс.env.Порт) вы можете слушать, и обрабатывает все запросы через прокси (так, вы приложение прослушивает этот порт и не беспокоится о прото - право?)

Итак, я правильно понял - у меня должен быть другой код для dev machine и Heroku?

Как

...
app = express()
...

if process.env.NODE_ENV == 'production'
  app.listen(process.env.PORT)
else
  https = require('https')
  http = require('http')
  http.createServer(app).listen(5080) # some local port
  options = {
    key: fs.readFileSync('key.pem'), 
    cert: fs.readFileSync('cert.pem') # my self-signed files
  }
  https.createServer(options, app).listen(5443) # some different local port

это правильный способ справиться с этим?

3 ответов


для задач Coffeescript - вот версия ответа Guard, преобразованная в Javascript. Я использовал другой подход к разделению утверждений if else.

var express = require('express');
var http = require('http');
var https = require('https');
var fs = require('fs');
var privateKey = fs.readFileSync('./config/localhost.key').toString();
var certificate = fs.readFileSync('./config/localhost.crt').toString();

var options = {
  key : privateKey
, cert : certificate
}

var app = express();

// Start server.
var port = process.env.PORT || 3000; // Used by Heroku and http on localhost
process.env['PORT'] = process.env.PORT || 4000; // Used by https on localhost

http.createServer(app).listen(port, function () {
    console.log("Express server listening on port %d in %s mode", this.address().port, app.settings.env);
});

// Run separate https server if on localhost
if (process.env.NODE_ENV != 'production') {
    https.createServer(options, app).listen(process.env.PORT, function () {
        console.log("Express server listening with https on port %d in %s mode", this.address().port, app.settings.env);
    });
};

if (process.env.NODE_ENV == 'production') {
    app.use(function (req, res, next) {
        res.setHeader('Strict-Transport-Security', 'max-age=8640000; includeSubDomains');
        if (req.headers['x-forwarded-proto'] && req.headers['x-forwarded-proto'] === "http") {
            return res.redirect(301, 'https://' + req.host + req.url);
        } else {
            return next();
            }
    });
} else {
    app.use(function (req, res, next) {
        res.setHeader('Strict-Transport-Security', 'max-age=8640000; includeSubDomains');
        if (!req.secure) {
            return res.redirect(301, 'https://' + req.host  + ":" + process.env.PORT + req.url);
        } else {
            return next();
            }
    });

};

Ну, сообщество выглядит довольно мертвым в эти дни (надеюсь, что я ошибаюсь)

ответ:

a) да, это способ справиться с этим

b) способ проверить, находитесь ли вы в безопасном режиме или нет, также зависит от окружающей среды:

if process.env.NODE_ENV == 'production'
  is_secure = (req) ->
    req.headers['x-forwarded-proto'] == 'https'
else
  is_secure = (req) -> req.secure

добавить Если вы хотите принудительно HTTPS:

redirect_to_https = (req, res, next) ->
  if not is_secure(req)
    res.redirect config.SECURE_DOMAIN + req.url
  else
    next()

app
  .use(redirect_to_https)

можно использовать app.enable('trust proxy'), потом req.secure boolean (http/https) работает также на Heroku или за любым совместимым прокси-сервером SSL.