Heroku 将 Next.js React 客户端应用程序 http 重定向到 https

Posted

技术标签:

【中文标题】Heroku 将 Next.js React 客户端应用程序 http 重定向到 https【英文标题】:Heroku redirect Next.js React client app http to https 【发布时间】:2019-11-13 01:29:17 【问题描述】:

我在 Heroku 上部署了一个 express 服务器:https://server.mydomain.com

还有一个 Next.js React 应用也部署在 Heroku 上:https://app.mydomain.com

它们的 SSL 证书都由 Heroku 自动配置,当我访问 https 域时,它们按预期工作。

我遇到的问题是当我访问http://app.mydomain.com时,它没有重定向到https://app.mydomain.com。

我在网上找到的所有解决方案都指向在服务器上强制使用 SSL:

this popular question 表示要检查 x-forwarded-proto 值:
/* 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://app.mydomain.com'+req.url)
 else
   next() /* Continue to other routes if we're not redirecting */
)
和其他人建议使用express-sslify 或heroku-ssl-redirect 之类的包。

这些解决方案适用于服务器请求,但加载 React 客户端页面不一定会触发 app.get()。显然,React 客户端可以独立于服务器运行。

所以问题是: 有人如何为 Heroku 上的子域 Next.js React 客户端应用强制 https?不使用快速服务器方法?

【问题讨论】:

你在为你的测功机付钱吗? 我有两个应用程序部署到 Heroku,一个在付费帐户上,一个在非付费帐户上。付费的会自动重新路由到 https,而免费的则不会。 是的。两者都是付费的。 你的 Procfile 是什么样的? 睡在上面,Obviously, a React client can run independently of a server. 伸出来。客户端需要服务器,heroku 很可能通过节点服务器(我认为这是默认的 Web 服务器)为您的静态文件夹提供服务。您需要做的是构建一个 express 应用程序来提供您的静态构建文件,并有一个 Procfile 告诉 heroku 针对该 express 应用程序而不是直接针对您的 react 应用程序运行节点。 【参考方案1】:

我在我的一个生产应用程序中执行此操作。

我们准备下一个应用程序对象并初始化一个快速服务器。这是在 server.js 文件中完成的。您可以在docs about a custom server 中了解更多信息。

Next.js 在其 github 的示例文件夹中也有一个关于自定义快速服务器的示例。我是here。

const express = require('express');
const next = require('next');

const dev = process.env.NODE_ENV !== 'production';
const app = next( dev );

const handle = app.getRequestHandler();

app
  .prepare()
  .then(() => 

    const server = express();

    server.use((req, res, next) => 
      const hostname = req.hostname === 'www.app.domain.com' ? 'app.domain.com' : req.hostname;

      if (req.headers['x-forwarded-proto'] === 'http' || req.hostname === 'www.app.domain.com') 
        res.redirect(301, `https://$hostname$req.url`);
        return;
      

      res.setHeader('strict-transport-security', 'max-age=31536000; includeSubDomains; preload');
      next();
    );

    server.get('*', (req, res) => handle(req, res));

    server.listen(
      4242,
      error => 
        if (error) throw error;
        console.error('Listening on port 4242');
      
    );

  )
  .catch(error => 
    console.error(error);
    process.exit(1);
  );

至于部署到 Heroku,您应该可以自定义 npm start 脚本来启动 nextjs,如下所示:

"scripts": 
  "dev": "next",
  "build": "next build",
  "start": "next start"

Heroku 还会自动运行 npm run build,因此它应该为您构建应用程序。

【讨论】:

在 Next.js 应用程序的上下文中,您将其具体放在哪里,以及如何部署 Heroku? @5tormTrooper 认为这很明显......我会更新答案 先生,您是一位绅士和一位学者。有效!感谢您花时间如此清晰地概述它。非常感激! ? @5tormTrooper 很高兴我能帮上忙 :) 有没有办法在不使用自定义服务器的情况下做到这一点?【参考方案2】:

Heroku 目前不向force the use of https for node apps“提供开箱即用”功能。

但是,随着 Nextjs v12 的发布,您无需设置 custom server 并改用 middleware 即可完成此操作。

参见this answer 的示例代码和middlewarecustom server 的优势。

我还发布了npm package 来处理这个问题:

import sslRedirect from 'next-ssl-redirect-middleware';
export default sslRedirect();

【讨论】:

以上是关于Heroku 将 Next.js React 客户端应用程序 http 重定向到 https的主要内容,如果未能解决你的问题,请参考以下文章

如何将带有 Mongodb 的 Next.js 应用程序部署到 Heroku?

Next.Js 带有样式组件的 React 应用程序。警告:道具 `className` 不匹配。服务器:“x” 客户端:“y”

Next.js 中的客户端初始化与静态 HTML 导出

Next.js 具有 React 钩子和 localStorage 的持久状态

Next.js/React 在组件中生成随机值时发出警告

React-tooltip 和 Next.js s-s-r 问题