【Next】服务端接口

Next.js 15( App Router 体系保持一致)如何处理 RESTful API,包括 GETPOSTPATCHDELETE 等请求,以及动态请求的写法。


1. Next.js 15 中的 API 路由体系

App Routerapp/ 目录)中,API 路由使用 route.tsroute.js 来定义。

  • 每个文件夹可以有一个 route.ts 文件。
  • 文件中导出的方法名要与 HTTP 请求方法一致:GETPOSTPATCHDELETE 等。
  • 返回值通常是 NextResponse

目录结构示例:

app/
 └── api/
      └── users/
           └── route.ts
  • 目录app/api/.../route.ts
  • 函数名:和 HTTP 方法对应:GETPOSTPATCHDELETE
  • 动态路由:用 [id] 文件夹,参数通过 params 获取。
  • 返回:统一用 NextResponse.json(data, {status})

2. RESTful API 思想

RESTful API 的基本原则:

  • 资源用名词表示(如 /api/users 而不是 /api/getUsers)。

  • 操作由 HTTP 方法表示:

    • GET /api/users → 获取用户列表
    • POST /api/users → 创建新用户
    • GET /api/users/:id → 获取某个用户
    • PATCH /api/users/:id → 修改某个用户
    • DELETE /api/users/:id → 删除某个用户

3. GET 请求

获取数据的 API。

// app/api/users/route.ts
import { NextResponse } from 'next/server';

export async function GET() {
  const users = [
    { id: 1, name: 'Tom' },
    { id: 2, name: 'Jerry' },
  ];
  return NextResponse.json(users);
}

调用:

const res = await fetch('/api/users');
const data = await res.json();
console.log(data);

URL 查询参数(Search Params)

  • 查询参数写在 URL 后面,例如 /api/users?name=Tom&age=20
  • route.ts 里可以通过 req.urlnew URL(req.url) 获取。
// app/api/users/route.ts
import { NextResponse } from 'next/server';

export async function GET(req: Request) {
  const { searchParams } = new URL(req.url);
  const name = searchParams.get('name');
  const age = searchParams.get('age');
  
  return NextResponse.json({ name, age });
}

调用:

await fetch('/api/users?name=Tom&age=20');

Headers 标头

  • 请求和响应都可以操作 Headers
  • 常用于 身份验证、内容类型、跨域控制等。
// app/api/headers/route.ts
import { NextResponse } from 'next/server';

export async function GET(req: Request) {
  const auth = req.headers.get('authorization'); // 取请求头
  const res = NextResponse.json({ message: 'ok' });
  res.headers.set('X-Custom-Header', 'Next15');  // 设置响应头
  return res;
}

调用:

await fetch('/api/headers', {
  headers: { Authorization: 'Bearer 123456' }
});

Cookie

Next.js 提供了 cookies() 来获取和设置 Cookie。

// app/api/cookies/route.ts
import { NextResponse } from 'next/server';
import { cookies } from 'next/headers';

export async function GET() {
  const cookieStore = cookies();
  const token = cookieStore.get('token')?.value;

  const res = NextResponse.json({ token });
  res.cookies.set('token', 'abc123', { httpOnly: true });
  return res;
}

4. POST 请求

创建数据,接收 body

// app/api/users/route.ts
import { NextResponse } from 'next/server';

export async function POST(req: Request) {
  const body = await req.json(); // 解析请求体
  const newUser = { id: Date.now(), ...body };
  return NextResponse.json(newUser, { status: 201 });
}

调用:

await fetch('/api/users', {
  method: 'POST',
  body: JSON.stringify({ name: 'Alice' }),
  headers: { 'Content-Type': 'application/json' }
});

5. 动态请求处理(路径参数)

如果要支持 /api/users/[id],可以用文件夹 [id]

app/api/users/[id]/route.ts

示例:

// app/api/users/[id]/route.ts
import { NextResponse } from 'next/server';

export async function GET(_: Request, { params }: { params: { id: string } }) {
  return NextResponse.json({ id: params.id, name: 'Mock User' });
}

调用:

const res = await fetch('/api/users/123');
const user = await res.json();
console.log(user); // { id: "123", name: "Mock User" }

6. PATCH 请求

用于部分更新。

// app/api/users/[id]/route.ts
import { NextResponse } from 'next/server';

export async function PATCH(req: Request, { params }: { params: { id: string } }) {
  const body = await req.json();
  return NextResponse.json({
    message: `User ${params.id} updated`,
    update: body,
  });
}

调用:

await fetch('/api/users/123', {
  method: 'PATCH',
  body: JSON.stringify({ name: 'Updated Name' }),
  headers: { 'Content-Type': 'application/json' }
});

7. DELETE 请求

删除资源。

// app/api/users/[id]/route.ts
import { NextResponse } from 'next/server';

export async function DELETE(_: Request, { params }: { params: { id: string } }) {
  return NextResponse.json({ message: `User ${params.id} deleted` });
}

调用:

await fetch('/api/users/123', { method: 'DELETE' });

8. 重定向(Redirect)

  • NextResponse.redirect() 进行接口级别重定向。
  • 常用于 登录校验,未登录就跳到 /login
// app/api/redirect/route.ts
import { NextResponse } from 'next/server';

export async function GET() {
  return NextResponse.redirect('https://example.com');
}

9. 接口处理的缓存

  • 静态缓存:在 fetch 时配置缓存策略。
  • 动态接口:默认不缓存,需要显式声明。

常见方式:

// 禁止缓存(强制动态)
export const dynamic = 'force-dynamic';

// 静态缓存 60 秒
export const revalidate = 60;

// GET 请求里设置响应缓存头
import { NextResponse } from 'next/server';

export async function GET() {
  const res = NextResponse.json({ time: Date.now() });
  res.headers.set('Cache-Control', 's-maxage=60, stale-while-revalidate=30');
  return res;
}

10. Middleware(中间件)

  • 文件位置:middleware.ts(放在项目根目录)。
  • 可以在请求进入 API 或页面之前进行拦截,适合做 权限验证 / 日志记录 / 重定向
// middleware.ts
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';

export function middleware(req: NextRequest) {
  const token = req.cookies.get('token')?.value;
  
  // 没有 token 就跳到登录页
  if (!token && req.nextUrl.pathname.startsWith('/api/secure')) {
    return NextResponse.redirect(new URL('/login', req.url));
  }

  // 给请求加自定义头
  const res = NextResponse.next();
  res.headers.set('X-Middleware', 'Hit');
  return res;
}

// 配置生效范围
export const config = {
  matcher: ['/api/:path*'], // 拦截所有 /api 路径
};
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

秀秀不只会前端

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值