【问题标题】:Node.JS, Express and Heroku - how to handle HTTP and HTTPS?Node.JS、Express 和 Heroku - 如何处理 HTTP 和 HTTPS?
【发布时间】:2012-10-22 13:48:11
【问题描述】:

我有一个非常普通的 Express 应用程序 - 简单的服务器逻辑、视图、大量客户端 JS。 我必须做很多 AJAX 请求。其中一些需要通过 HTTPS 协议保护(一些不需要)。

所以,我的服务器应该同时使用 HTTP 和 HTTPS。 它也应该适用于本地机器(通常使用 nodemon 运行)和 Heroku。

据我了解,Heroku 为您提供了一个您可以监听的端口 (process.env.PORT),并通过代理处理所有请求(因此,您的应用程序正在监听此端口,而无需担心 proto - 对吧?)

那么,我做对了吗?我应该为开发机器和 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

这是处理这个问题的正确方法吗?

【问题讨论】:

    标签: node.js heroku express


    【解决方案1】:

    您可以使用app.enable('trust proxy'),然后req.secure boolean (http/https) 也可以在 Heroku 上运行,或者在任何兼容的 SSL 终止代理之后运行。

    【讨论】:

    【解决方案2】:

    对于 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();
                }
        });
    
    };
    

    【讨论】:

      【解决方案3】:

      嗯,这些天社区看起来已经死了(希望我错了)

      答案是:

      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)
      

      【讨论】:

      • 一个简单的问题 - 我们可以从配置中获取像 return res.redirect('https://' + req.headers.host + req.url); 这样的主机吗?
      • 可能是的,但为了消除冗余是为了什么?您从浏览器获取标题。从配置(或环境变量)中获取重要值对我来说似乎是一个更可靠的选择
      猜你喜欢
      • 2013-12-21
      • 1970-01-01
      • 2014-07-04
      • 2015-07-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-02-01
      • 1970-01-01
      相关资源
      最近更新 更多