【Next】服务端接口
Next.js 15( App Router 体系保持一致)如何处理 RESTful API,包括 GET
、POST
、PATCH
、DELETE
等请求,以及动态请求的写法。
1. Next.js 15 中的 API 路由体系
在 App Router(app/
目录)中,API 路由使用 route.ts
或 route.js
来定义。
- 每个文件夹可以有一个
route.ts
文件。 - 文件中导出的方法名要与 HTTP 请求方法一致:
GET
、POST
、PATCH
、DELETE
等。 - 返回值通常是
NextResponse
。
目录结构示例:
app/└── api/└── users/└── route.ts
- 目录:
app/api/.../route.ts
- 函数名:和 HTTP 方法对应:
GET
、POST
、PATCH
、DELETE
。 - 动态路由:用
[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.url
或new 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 路径
};