如何在代理后面的服务器端 Next.js v13 应用程序中从域重定向到另一个域

问题描述 投票:0回答:1

我确实有很多域,我想将它们重定向到一个主域。

域列表:

  • example.com
  • example1.com
  • example2.com
  • example3.com

我想从其他域重定向的主域是

example.com

有一个很好的答案,可以将服务器端的 Next.js 重定向到不同的路径。

Next.js >= 12 现在您可以使用中间件进行重定向,在pages文件夹(或pages内的任何子文件夹)内创建一个_middleware.js文件

import { NextResponse, NextRequest } from 'next/server'
export async function middleware(req, ev) {
    const { pathname } = req.nextUrl
    if (pathname == '/') {
        return NextResponse.redirect('/hello-nextjs')
    }
    return NextResponse.next() } 

来源:https://stackoverflow.com/a/58182678/10826693

注意: 对于 Next.js v13,您必须在 Next.js 的根目录中创建

middleware.js
文件,而不是该答案中提到的
pages/_middleware.js

如果我尝试重定向到另一个域,根目录中的 middleware.ts 中的 TypeScript 代码如下所示:

/* eslint-disable @next/next/no-server-import-in-page */
import { NextResponse, NextRequest } from 'next/server'

export async function middleware(req: NextRequest) {
    const url = req.nextUrl.clone()
    console.log(url.host) //logs localhost:3000

    if (!url.host.match(/example.com/)) {
        url.host = 'example.com'
        return NextResponse.redirect(url) //never executes because the URL is always localhost in the Docker container
    }
    return NextResponse.next()
}

但是,在代理服务器后面的 Docker 容器中运行的 Next.js v13 应用程序始终在主机中具有

localhost
URL。 Docker 容器中的
url.host
始终等于 URL localhost 以及容器内定义的端口(例如
localhost:3000
)。

当我在服务器端只有

example1.com
时,如何将域
example2.com
example3.com
example.com
重定向到
localhost
,包括相同的路径、查询参数和哈希?

docker redirect next.js proxy middleware
1个回答
8
投票

如果要将 Docker 容器中的所有域重定向到主域,则需要从

X-Forwarded-Host
标头中获取重定向的 URL。

除了主机之外,您还必须设置正确的端口(80/443 - 标头称为

X-Forwarded-Port
)和协议(http/https - 标头称为
X-Forwarded-Proto
)。

Next.js v13 在应用程序的

middleware.ts
文件夹中创建
src
文件,并将生产中与
example.com
域不匹配的所有域重定向到该文件。

/* eslint-disable @next/next/no-server-import-in-page */
import { NextRequest, NextResponse } from 'next/server';

export function middleware(request: NextRequest) {
  const url = request.nextUrl.clone();

  const isProduction = process.env.NODE_ENV === 'production' // redirect only in production
  const requestedHost = request.headers.get('X-Forwarded-Host');

  if (isProduction && requestedHost && !requestedHost.match(/example.com/)) {
    const host = `example.com`; // set your main domain

    const requestedPort = request.headers.get('X-Forwarded-Port');
    const requestedProto = request.headers.get('X-Forwarded-Proto');

    url.host = host;
    url.protocol = requestedProto || url.protocol;
    url.port = requestedPort || url.port;

    return NextResponse.redirect(url);
  }

  return NextResponse.next();
}

export const config = {
  matcher: '/',
};

现在所有域

example1.com
example2.com
example3.com
都被重定向到
example.com
,包括相同的路径、查询参数和哈希。

© www.soinside.com 2019 - 2024. All rights reserved.