我在Heroku上运行了一个NodeJS HTTP(非S)服务器。我已配置SSL,它接受HTTPS请求。我使用vanilla HTTP服务器的原因是the following:
SSL termination occurs at Heroku's load balancers; they send your app plain (non-SSL) traffic, so your app should create a non-HTTPS server."
不幸的是,我的应用程序仍然响应普通的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配置。
答案 0 :(得分:1)
最好使用app.use(function(req, res, next{ /* ... */ });
来捕获其他HTTP方法。
答案 1 :(得分:1)
因此,假设您将此放在中间件链的最前端,在路由器本身之前,这应该是非常高效的。
但是让我们把它提升一个档次。假设您在多个环境中部署此服务器,而不仅仅是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库,特别是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' }
答案 2 :(得分:0)
如果有人仍在寻找解决方案,请在您的NodeJ和Express JS文件中创建一个函数。
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);