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

w41d8nur  于 12个月前  发布在  React
关注(0)|答案(3)|浏览(165)

我在Heroku上部署了一个Express服务器:https://server.mydomain.com
还有一个Next.js React应用也部署在Heroku上:https://app.mydomain.com
两者都有Heroku自动配置的SSL证书,当我访问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上为子域Next.js React客户端应用强制https?而不使用express server方法?

gajydyqb

gajydyqb1#

我在一个生产应用程序中这样做。
我们准备下一个app对象并初始化一个express服务器。这在server.js文件中完成。你可以在关于自定义服务器的文档中阅读更多。
在github的examples文件夹中,Next.js也有一个关于自定义express服务器的例子,它是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,因此它应该为您构建应用程序。

zlhcx6iw

zlhcx6iw2#

Heroku目前没有为force the use of https for node apps提供“开箱即用”的功能。
但是,随着Nextjs v12的发布,您可以在无需设置custom server并使用middleware的情况下实现这一点。
请参阅此答案,了解middlewarecustom server的示例代码和优势。
我还发布了一个npm package来处理这个问题:

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

字符串

9wbgstp7

9wbgstp73#

来自@ jobio-cunha的答案很棒,对我也很有效。我不得不做一些小的调整,以便与我的heroku应用程序(2023年底部署)一起使用。
我的heroku NODE_ENV正在重新生成。以下更改已解决

const dev = process.env.NODE_ENV !== 'PRODUCTION'

字符串

const dev = process.env.NODE_ENV !== 'production'


在if语句中使用or导致了一个错误,这似乎是由于应用程序重定向时的无限重定向,命中中间件-传递了if条件,然后再次重定向。
所以对我来说,

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


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


否则工作就像一个魅力。非常感谢@5tormTrooper的问题和若昂库尼亚的答案。

相关问题