Node.js HTTPS NodeJS和Heroku。强制使用HTTPS?

Node.js HTTPS NodeJS和Heroku。强制使用HTTPS?,node.js,ssl,heroku,https,Node.js,Ssl,Heroku,Https,我有一个在Heroku上运行的NodeJS HTTP(非S)服务器。我已经配置了SSL,它接受对HTTPS的请求。我使用普通HTTP服务器的原因是: 不幸的是,我的应用程序仍然响应普通的HTTP请求。我想强制从HTTP重定向到HTTPS。我可以用一些中间件来实现这一点: /* At the top, with other redirect methods before other routes */ app.get('*',function(req,res,next){ if(req.hea

我有一个在Heroku上运行的NodeJS HTTP(非S)服务器。我已经配置了SSL,它接受对HTTPS的请求。我使用普通HTTP服务器的原因是:

不幸的是,我的应用程序仍然响应普通的HTTP请求。我想强制从HTTP重定向到HTTPS。我可以用一些中间件来实现这一点:

/* At the top, with other redirect methods before other routes */
app.get('*',function(req,res,next){
  if(req.headers['x-forwarded-proto']!='https')
    res.redirect('https://mypreferreddomain.com'+req.url)
  else
    next() /* Continue to other routes if we're not redirecting */
})
但这是一个好的解决方案吗?POST请求是如何工作的?如果我发布到HTTP,应该允许吗


我想的最后一种方法是使用Nginx并在其中插入一个从HTTP到HTTPS的重定向。不幸的是,Heroku不允许Nginx配置。

最好使用
app。使用(function(req,res,next{/*…*/});
捕获其他HTTP方法。

因此,假设您将其放在中间件链的最前端,在路由器本身之前,这应该是非常有效的

但是让我们更进一步。假设您将此服务器部署在多个环境中,而不仅仅是Heroku,那么如果您希望协调多个环境的行为,您将很难避免在中间件中执行一些有条件的包含或在其中执行恒定的有条件的分支

如果您为Heroku编写了一个特定的服务器,您可以跳过所有这些,大致如下:

var app = require('./app').createApp();
var server = require('http').createServer(function (req, res) {
    if (!secure(req)) {
        // Redirect
        res.statusCode = 302;
        res.setHeader('Location', pathname);
        res.setHeader('Content-Length', '0');
        res.end();
    } else {
        app.handle(req, res);
    }
});
server.listen(80);
此外,尽量避免手动构造url。您应该真正尝试使用库,特别是
url.parse()
url.resolve()
函数,因为解析和构造url是非常重要的(请考虑隐式/显式尾部斜杠、哈希、查询和url编码)

下面是一个小预览:

var url = require('url');

url.parse('http://www.foo.com?bar=baz#quux')
{ protocol: 'http:',
  slashes: true,
  auth: null,
  host: 'www.foo.com',
  port: null,
  hostname: 'www.foo.com',
  hash: '#quux',
  search: '?bar=baz',
  query: 'bar=baz',
  pathname: '/',
  path: '/?bar=baz',
  href: 'http://www.foo.com/?bar=baz#quux' }

如果有人仍在寻找解决方案,请在NodeJs和expressjs文件中创建一个函数

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

app.use(enforceSsl);

您的问题很可能是小写标题arg name
x-forwarded-proto
,它必须与数组中的键不匹配,因为heroku创建的标题以大写字母开头:
x-forwarded-proto
。您可以通过更改标题名或使用
reg.get('x-forwarded-proto')来解决此问题
您将得到结果,因为它不区分大小写。
app.use(enforceSsl);