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

smk*_*ber 11 ssl heroku express reactjs

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

我有一个 server.js 文件并表示我只是为了尝试运行中间件,然后为我的 React 应用程序提供服务。

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

solutions今天从 StackOverflow、Google 和其他地方尝试了很多很多,但没有一个解决方案对我有用。我也没有任何错误。它只是不起作用。

尝试使用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);
Run Code Online (Sandbox Code Playgroud)

另一种尝试使用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);
Run Code Online (Sandbox Code Playgroud)

尝试使用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);
Run Code Online (Sandbox Code Playgroud)

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

小智 11

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

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

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

  • 我只是好奇在应用程序层处理这个问题是否会产生任何后果?索引不同?搜索引擎优化? (4认同)

Fre*_*sar 10

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

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

Web 服务器可以通过静态 buildpack 进行配置

配置文件static.json应提交到存储库的根目录。如果该文件位于子目录中,则无法识别

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

{
  "root": "build/",
  "routes": {
    "/**": "index.html"
  }
}
Run Code Online (Sandbox Code Playgroud)

仅 HTTPS

通过自动将不安全请求重定向到https://来强制安全连接,如下所示static.json

{
  "root": "build/",
  "routes": {
    "/**": "index.html"
  },
  "https_only": true
}
Run Code Online (Sandbox Code Playgroud)

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