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

Next.js 15中如何在Server Action内获取pathname?

在Next.js 15中,能否在Server Action内获取pathname?

在路由处理器中,我们可以通过request对象直接获取pathname:

export async function GET(request) {
  const url = new URL(request.url);
  console.log(url.pathname);
}

但Server Action中没有request对象,我目前的临时方案是从客户端组件传入pathname:

客户端组件代码

import { useTransition } from "react";
import { usePathname } from "next/navigation";
import { signout } from "@/lib/actions";

export default function Component() {
  const [isPending, startTransition] = useTransition();
  const pathname = usePathname();

  const handleClick = () => {
    startTransition(async () => {
      await signout({ pathname });
    })
  }

  return <Button onClick={handleClick} disabled={isPending}>Logout</Button>
}

Server Action代码

import { deleteSession } from "@/lib/session";
import { redirect } from "next/navigation";

export async function signout(data) {
  const { pathname } = data;
  await deleteSession();

  redirect(pathname);
}

我需要这次页面重载来重新运行middleware中的会话检查,middleware代码如下:

import { NextResponse } from "next/server";
import { getSession, updateSession } from "./lib/session";

export async function middleware(request) {
  await updateSession();

  if (request.nextUrl.pathname.startsWith("/protected")) {
    // 需要会话验证,否则跳转到登录页
    const session = await getSession();
    if (!session)
      return NextResponse.redirect(
        new URL("/signin?back=" + request.nextUrl.pathname, request.url)
      );
  }

  if (request.nextUrl.pathname.startsWith("/signin")) {
    const session = await getSession();
    if (session)
      return NextResponse.redirect(
        new URL(request.nextUrl.searchParams.get("back") || "/", request.url)
      );
  }

  return NextResponse.next();
}

现在想请教:有没有办法直接在Server Action内获取pathname?或者无需知道pathname就能从Server Action中触发当前页面的重载?


可行解决方案

1. 直接在Server Action中获取pathname

在Next.js 15中,Server Action可以通过headers()函数获取请求头里的referer字段,解析该字段即可得到当前页面的pathname:

import { headers } from "next/headers";
import { deleteSession } from "@/lib/session";
import { redirect } from "next/navigation";

export async function signout() {
  const refererHeader = headers().get("referer");
  // 处理referer字段不存在的情况,默认跳转到首页
  const pathname = refererHeader ? new URL(refererHeader).pathname : "/";
  
  await deleteSession();
  redirect(pathname);
}

注意:referer字段可能被浏览器隐私设置或代理服务器禁用,所以必须添加降级逻辑。

2. 无需指定pathname,触发页面重载

如果你只是想触发页面重载来运行middleware的会话检查,最直接的方式就是在Server Action中重定向到当前页面的路径——其实和方案1逻辑一致,利用referer字段实现。

3. 优化现有客户端传参方案

你当前从客户端通过usePathname()传入pathname的方案是最稳定的,因为它能精准获取当前路由。可以给Server Action添加默认值,避免传入空值导致错误:

import { deleteSession } from "@/lib/session";
import { redirect } from "next/navigation";

export async function signout(data = {}) {
  const { pathname = "/" } = data;
  await deleteSession();
  redirect(pathname);
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 16:50:56