【问题标题】:Why cannot I redirect my React app on Heroku from http to https?为什么我不能将 Heroku 上的 React 应用程序从 http 重定向到 https?
【发布时间】:2018-07-30 11:16:29
【问题描述】:

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

我有一个 server.js 文件,我使用 express 来尝试运行中间件,然后为我的 React 应用程序提供服务。

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

我今天从 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 帖子的随机节点安装,但没有任何效果。如果没有任何错误,我很难弄清楚为什么这不起作用。

【问题讨论】:

标签: reactjs express ssl heroku


【解决方案1】:

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

因为您是通过 Heroku 使用 create-react-app 部署您的 react 应用程序,并且它是 buidlpack(推荐,如果您不是:create-react-app-buildpack)。正如官方文档所说:

网络服务器可能是configured via the static buildpack

配置文件static.json 应该在repo 的根目录下提交。如果此文件在子目录中,将无法识别

默认static.json,如果repo中不存在,则为:

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

仅 HTTPS

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

中实施安全连接
{
  "root": "build/",
  "routes": {
    "/**": "index.html"
  },
  "https_only": true
}

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

【讨论】:

    【解决方案2】:

    尝试将此添加到您的 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>
    

    【讨论】:

      【解决方案3】:

      尝试将以下内容添加到 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 文件上方运行

      【讨论】:

      • 奇怪的是,我需要做一个 else if() 并独立声明每个 host 字符串才能使其工作,这没有任何意义,但仍然如此。例如let longUrl = 'www.url.com'let shortUrl = 'url.com'...if (longUrl === ....)...else if (shortUrl === .... ).
      • @misterfoxy 只想说个人“谢谢”,因为您的回答为我节省了很多时间 :)
      • 我只是好奇在应用层处理这个是否有任何后果?索引不同?搜索引擎优化?
      【解决方案4】:

      尝试使用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'));
      });
      

      【讨论】:

      • 我一回到家就试试这个。谢谢。
      • 这似乎也失败了。如果我输入 url sans https 或使用 http,它只会转到非安全 url。在网址中使用https,它可以像希望的那样工作,但我无法让它从http重定向到https。
      猜你喜欢
      • 2019-11-13
      • 2018-09-20
      • 2020-03-19
      • 2021-08-31
      • 2018-05-12
      • 2013-02-13
      • 1970-01-01
      • 2021-04-13
      • 2014-05-14
      相关资源
      最近更新 更多