【问题标题】:How do I force or redirect my next.js website to use https如何强制或重定向我的 next.js 网站以使用 https
【发布时间】:2021-06-02 02:21:49
【问题描述】:

我认为这将是一项简单的任务,但我很难找到一种方法来强制我的网页使用 https。 next.js webapp 位于 heroku 服务器上,我已经设置了 SSL。 https 和 http 版本都有效,但是如何强制或重定向网站以使用 https 版本。 我已经看到了一些使用 express 的解决方案,但是我的 webapp 中没有任何东西使用 express,这是必需的吗? 谢谢。

【问题讨论】:

标签: ssl redirect https next.js


【解决方案1】:

从 Nextjs v12 开始,您可以使用 middleware 而不是设置 custom server

中间件是更好的解决方案,原因如下:

  • 自定义服务器通常需要额外的依赖项(如 express)
  • 你放弃了一些盒子功能,比如automatic static optimization
  • 使用内置路由范式,中间件可以作用于特定路径

创建一个类似于以下内容的/pages/_middleware.ts(或.js)文件:

import  { NextFetchEvent, NextRequest, NextResponse } from 'next/server'

type Environment = "production" | "development" | "other";
export function middleware(req: NextRequest, ev: NextFetchEvent) {
    const currentEnv = process.env.NODE_ENV as Environment;

    if (currentEnv === 'production' && 
        req.headers.get("x-forwarded-proto") !== "https") {
        return NextResponse.redirect(
           `https://${req.nextUrl.hostname}${req.nextUrl.pathname}`,
           301
        );
    } 
    return NextResponse.next();
}

我还创建了一个npm package for this

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

【讨论】:

  • 问题在于,无论您在何处部署此代码,req.nextUrl.hostname 将始终解析为 localhost。因为服务器内部在本地主机上运行。 example.com/page-1 ===> localhost/page-1
  • @LakshitNagar req.nextUrl 应该包含来自客户端的请求 url。我可以确认这就是它在 heroku 中的工作方式(我正在积极使用这个包并且它可以工作)。尽管nextUrl github.com/vercel/next.js/issues/31533#issuecomment-1010597076 有一些奇怪的行为
  • 我猜如果您使用 localhost 向您的服务发出 Intranet 请求,那么它将无法正常工作......不确定下一个 js 实际有多常见(此解决方案应该适用于外部流量)跨度>
  • 对于在这里搜索的任何人,我发现 req.headers.get('host') 返回请求的 true 主机(例如“yoursite.com”) ,而 req.nextUrl.host 将始终返回 'localhost:3000' (或您使用的任何端口)
  • @NSjonas 我托管在 Heroku 上——一个带有自动配置 SSL 的自定义域。这是我的项目中间件文件的链接:github.com/caleb531/faith-dashboard/blob/master/pages/…
【解决方案2】:

有一个名为heroku-ssl-redirect 的 NPM 库的解决方案。

首先,使用npm i heroku-ssl-redirect 安装库。

然后,使用以下脚本创建一个新的server.js 文件。

const next = require('next');
const express = require('express');
const sslRedirect = require('heroku-ssl-redirect').default; // to make it work with 'require' keyword.

const PORT = process.env.PORT || 3000;
const dev = process.env.NODE_ENV !== 'production';
const app = next({ dev });
const handle = app.getRequestHandler();

app.prepare().then(() => {
  const server = express();

  // Express's middleware to automatically redirect to 'https'.
  server.use(sslRedirect());

  server.all('*', (req, res) => {
    return handle(req, res);
  });

  server.listen(port, err => {
    if (err) throw err;

    console.log(`Server starts on ${PORT}.`);
  });
});

然后,将start 脚本改成这样:

"scripts": {
  "dev": "next",
  "build": "next build",
  "start": "node server.js"
}

它应该可以工作。

请注意,您可以使用本机 Node.js 的 http 模块中的 createServer 方法替换 Express。但我使用 Express 来简化语法。

延伸阅读:How to setup a custom server in Next.js.

【讨论】:

  • 所以解决方案是设置自定义服务器。好的,谢谢你的回答。我是这个 servers.js 的新手,但如果我没有设置自定义服务器,webapp 默认使用哪种服务器?只是想知道。
  • 默认使用 Node 的本地服务器。它是使用 Node http 模块制作的。哦,如果对您有帮助,请将答案标记为已接受。谢谢?。
  • 似乎这应该是下一个默认的开箱即用功能...惊讶于解决方法如此繁重...
  • 如果您使用 Vercel / netlify / 与您的部署平台类似的东西,那么它会自动执行 HTTPS 重定向。尤其是 Vercel,因为它是为 Next.js 制作的。
  • 注意:heroku 不会自动重定向到 https
猜你喜欢
  • 2022-08-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-06-20
  • 2020-06-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多