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

14

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

同时,我还在Heroku上部署了一个Next.js React应用程序:https://app.mydomain.com

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

我的问题是当我访问http://app.mydomain.com时,它不会重定向到https://app.mydomain.com

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

/* 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 */
})

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

所以问题是:如何在Heroku上强制使用https来处理子域名Next.js React客户端应用程序?而不使用express服务器方法?


我在Heroku上部署了两个应用程序,一个是付费账户,另一个是非付费账户。付费账户将自动重定向到https,而免费账户则不会。 - Jake Luby
是的。两者都需要付费。 - 5tormTrooper
你的 Procfile 是什么样子的? - Jake Luby
是的,React (Next.js) 应用程序托管在自己的应用程序上,使用自定义域名在爱好者动力上运行。 - 5tormTrooper
1
睡了一晚上,"显然,React客户端可以独立于服务器运行"这句话很突出。客户端需要一个服务器,而Heroku很可能是通过一个Node服务器来提供您的静态文件夹(我认为这是默认的Web服务器)。您需要构建一个Express应用程序来提供您的静态构建文件,并有一个Procfile告诉Heroku对该Express应用程序运行node,而不是直接运行React应用程序。 - Jake Luby
显示剩余5条评论
2个回答

7
我在我的一个生产应用程序中这样做。
我们准备下一个应用程序对象并初始化一个express服务器。这是在server.js文件中完成的。您可以在有关自定义服务器的文档中阅读更多信息。
Next.js在他们的Github示例文件夹中也有一个关于自定义express服务器的示例。它在这里
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认为这是显而易见的...我将更新答案。 - João Cunha
1
您,先生,是一位绅士和学者。它起作用了!感谢您花时间清晰地概述它。非常感谢! - 5tormTrooper
@5tormTrooper 很高兴我能帮到你 :) - João Cunha
有没有不使用自定义服务器的方法来实现这个? - insivika

2
Heroku目前不提供“开箱即用”的功能来强制使用https来运行Node应用程序。
然而,在Nextjs v12发布后,您可以通过使用中间件而无需设置自定义服务器来实现此目的。
请参见this answer以获取示例代码和中间件与自定义服务器的优势。
我还发布了一个npm包来处理这个问题:
import sslRedirect from 'next-ssl-redirect-middleware';
export default sslRedirect({});

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接