为什么我无法将Heroku上的React应用程序从http重定向到https?

时间:2018-02-20 06:49:36

标签: reactjs express ssl heroku

我在Heroku上有一个使用create-react-app创建的应用程序。就在今天,我使用Heroku的自动(-ish)SSL证书流程ExpeditedSSL获得了SSL证书,然后文档建议将所有http请求重新路由到https。

我有一个server.js文件并表达我只是试图运行中间件然后提供我的React应用程序。

我知道SSL证书的工作就好像我去https://myapp.com我看到了我的Heroku应用程序,但当我转到http://myapp.com时,它没有被重定向到我的Heroku应用程序的https版本。< / p>

我今天已经从StackOverflow,Google和其他方面尝试了很多很多solutions,并且这些解决方案都没有为我工作。我也没有收到任何错误。它只是没有用。

尝试使用https library

const https = require("https");
const express = require('express');
const app = express();

app.use(express.static(path.join(__dirname, 'build')));

app.get('/', function (req, res) {
  res.sendFile(path.join(__dirname, 'build', 'index.html'));
});

https.createServer(app).listen(3000);

使用heroku-ssl-redirect的另一次尝试:

var sslRedirect = require('heroku-ssl-redirect');
var express = require('express');
var app = express();

// enable ssl redirect
app.use(sslRedirect(['production'], 301));

app.use(express.static(path.join(__dirname, 'build')));

app.get('*', (req, res, next) => {
  if (req.headers['x-forwarded-proto'] != 'https'){
    res.redirect('https://' + req.hostname + req.url);
  } else {
    next();
  }
});

app.get('/', function (req, res) {
  res.sendFile(path.join(__dirname, 'build', 'index.html'));
});

app.listen(process.env.PORT || 3000);

尝试使用x-forward-proto

const express = require('express');
const env = process.env.NODE_ENV || 'development';
const bodyParser = require('body-parser');
const path = require('path');
const app = express();

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

if (env === 'production') {
  app.use(forceSsl);
}

app.use(express.static(path.join(__dirname, 'build')));

app.get('/', function (req, res) {
  res.sendFile(path.join(__dirname, 'build', 'index.html'));
});

app.listen(process.env.PORT || 8080);

我还尝试过各种博客和SO帖子中的一些随机节点安装,但没有任何效果。没有任何错误,我很难弄清楚为什么这不起作用。

4 个答案:

答案 0 :(得分:1)

尝试将以下内容添加到index.html文件的标题

<script>
var host = "www.URL.com" || "URL.com";
if ((host == window.location.host) && (window.location.protocol != "https:")){
window.location.protocol = "https";
}
</script>

我正在处理类似的问题,这让我可以解决它。将它放在标题中可确保脚本在任何捆绑的JavaScript之前运行,但我认为它可以在您的bundle.js文件之上运行

答案 1 :(得分:1)

以下更新和安全的解决方案:

因为您正在使用create-react-app通过Heroku部署React应用,并且它是buidlpack(如果不是,则建议使用:create-react-app-buildpack)。因此,正如官方文档所说:

Web服务器可能是configured via the static buildpack

配置文件static.json应该在存储库的根目录下提交。如果此文件位于子目录中,则不会被识别

如果仓库中不存在默认的static.json,则为:

{
  "root": "build/",
  "routes": {
    "/**": "index.html"
  }
}

仅HTTPS

通过自动将不安全的请求重定向到static.json中的 https://

{
  "root": "build/",
  "routes": {
    "/**": "index.html"
  },
  "https_only": true
}

@misterfoxy的方法有效,但方法不正确!

答案 2 :(得分:0)

尝试使用express-https-redirect

安装时:

npm install express-https-redirect --save

然后你应该可以做类似的事情:

const express = require('express');
const httpsRedirect = require('express-https-redirect');
const app = express();
app.use('/', httpsRedirect());
app.set('port', process.env.PORT || 3000);
app.use(express.static(path.join(__dirname, 'build')));

app.get('/', function (req, res) {
    res.sendFile(path.join(__dirname, 'build', 'index.html'));
});

app.listen(app.get('port'), function () {
        console.log('Express server listening on port ' + app.get('port'));
});

答案 3 :(得分:0)

尝试将其添加到index.html文件中 将其放在标头中,这样它将在其他脚本之前运行

<script>
const domain1 = "www.example.com";
const domain2 = "example.com";
const host = window.location.host;
if ((domain === host || domain2 === host) && (window.location.protocol !== "https:")){
  window.location.href = "https://www.example.com";
}
</script>