You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

NextJS中间件开发问题:API路径重写与请求转发失败

问题分析与修复方案

你的代码存在几个关键问题导致代理转发失效,下面逐一说明并给出修正后的完整代码:

核心问题点

  1. Request对象不可直接修改:原代码中直接调用request.headers.set()无效,NextJS的Request实例是不可变的,必须创建新的Request对象来修改头信息。
  2. Forward方法使用错误:@rescale/nemo的forward函数需要传递修改后的Request对象,而非NextResponse.next()的结果。
  3. 重写URL的路径处理不严谨:当segments为空(比如请求/api/proxy/)时,拼接后的路径为空字符串,会导致目标URL无效。
  4. Auth调用未异步等待:全局中间件中的auth()是异步函数,未加await会导致认证逻辑不生效。
  5. 全局Auth逻辑反转:原代码仅在请求包含api/auth时调用认证,这与常规的“保护非认证路由”逻辑相反。

修正后的完整代码

import { NextResponse } from "next/server";
import { cookies } from 'next/headers';
import { createMiddleware, type MiddlewareFunctionProps } from '@rescale/nemo'
import { auth } from 'auth';

const globalMiddlewares = {
  before: async ({ request }: MiddlewareFunctionProps) => {
    // 非auth路径需要验证身份,auth路径跳过(避免循环认证)
    if (!request.url.includes("api/auth")) {
      await auth();
    }
  },
};

const middlewares = {
  "/api/proxy/*segments": [
    async ({ request, forward, params }: MiddlewareFunctionProps) => {
      const sessionCookieName = process.env.NODE_ENV === "development"
        ? "authjs.session-token"
        : "__Secure-next-auth.session-token";
      const cookieStore = await cookies();
      const bearerToken = cookieStore.get(sessionCookieName);

      // 创建新的Request对象,修改Authorization头
      const newRequest = new Request(request);
      if (bearerToken?.value) {
        newRequest.headers.set("Authorization", `Bearer ${bearerToken.value}`);
      }

      // 传递修改后的请求到下一个中间件
      forward(newRequest);
    },
    async ({ params }: MiddlewareFunctionProps) => {
      const segments = params()?.segments || [];
      // 处理空路径情况,确保目标URL有效
      const path = segments.length > 0 ? segments.join("/") : "/";
      const apiBase = process.env.NEXT_PUBLIC_API_BASE;

      if (!apiBase) {
        throw new Error("NEXT_PUBLIC_API_BASE环境变量未配置");
      }

      // 构造目标URL并执行重写
      const targetUrl = new URL(path, apiBase);
      return NextResponse.rewrite(targetUrl);
    }
  ]
}

export const middleware = createMiddleware(middlewares, globalMiddlewares);

export const config = {
  matcher: ["/((?!_next/static|_next/image|favicon.ico).*)"],
}

关键修改说明

  • Request对象修改:通过new Request(request)创建可修改的请求实例,仅在token存在时设置Authorization头,避免空值导致的请求错误。
  • Forward逻辑修正:将修改后的Request传递给forward,确保后续中间件能拿到更新后的请求信息。
  • 路径容错处理:当segments为空时,默认使用根路径/,避免构造出无效的目标URL。
  • Auth逻辑修正:全局中间件中对非auth路径执行认证,并添加await确保认证完成后再继续请求。
  • 环境变量校验:添加对NEXT_PUBLIC_API_BASE的存在校验,提前暴露配置问题。

内容的提问来源于stack exchange,提问作者droid001

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 23:31:03