建立网站的关键是定位网页开发环境一般写什么
nextjs 官方文档(current branch 对应如下文档)
- Middleware
- path-to-regexp
本专栏内容均可在Github:test_05/Middleware 找到
一、middleware 基本使用
中间件允许您在请求完成之前运行代码。然后,根据传入的请求,您可以通过重写、重定向、修改请求或响应标头或直接响应来修改响应。
使用项目根目录中的 middleware.ts
文件(或 .js
)来定义中间件。例如,与 pages
或 app
处于同一级别,或者在 src
内(如果适用)。
注意 :
虽然每个项目仅支持一个 middleware.ts 文件,但您仍然可以模块化地组织中间件逻辑。将中间件功能分解为单独的 .ts 或 .js 文件,然后将其导入主 middleware.ts 文件。这样可以更清晰地管理路由特定的中间件,这些中间件会汇总在 middleware.ts 中以便进行集中控制。通过强制使用单个中间件文件,可以简化配置、防止潜在冲突并通过避免多个中间件层来优化性能。
Example:
将 /about/**
所有路由访问重定向到 /home
,见:middleware.ts
import { NextRequest, NextResponse } from "next/server";export const middleware = (request: NextRequest) => {// 请求路由为 /about/** 重定向到 /homereturn NextResponse.redirect(new URL("/home", request.url));
};/** 配置匹配路径 */
export const config = {matcher: "/about/:path*",
};
matcher
的语法参考 path-to-regexp
我们也可以不使用 matcher
,而是在 middleware
中使用条件语句进行判断,见:middleware.ts
import { NextRequest, NextResponse } from "next/server";export const middleware = (request: NextRequest) => {// 将 url 开头为 /about 的请求重定向到 /homeif (request.nextUrl.pathname.startsWith("/about")) {return NextResponse.redirect(new URL("/home", request.url));}
};
二、在中间件中使用 Cookies
Cookies
是常规标头。在 Request
中,它们存储在 Cookie
标头中。在 Response
中,它们位于 Set-Cookie
标头中。Next.js
通过 NextRequest
和 NextResponse
上的 cookies
扩展提供了一种访问和操作这些 cookie
的便捷方法。
对于传入请求, cookies
具有以下方法:
- get
- getAll
- set
- delete cookies
您可以使用 has
检查 cookie
是否存在,或使用 clear
删除所有 cookie。
对于传出的响应, cookies
具有以下方法
- get
- getAll
- set
- delete
见:middleware.ts
/** 二、中间件中使用 cookies */
export const middleware = (request: NextRequest) => {// cookie { name: 'vercel', value: '31321' }console.log(request.cookies.get("vercel"));/*** cookies [* { name: 'vercel', value: '31321' },* { name: 'nextjs', value: '333' }* ]*/console.log(request.cookies.getAll());// trueconsole.log("1、is has vercel :", request.cookies.has("vercel"));request.cookies.delete("vercel");// falseconsole.log("2、is has vercel :", request.cookies.has("vercel"));/** 设置 cookie */const response = NextResponse.next();response.cookies.set("vercel", "333");response.cookies.set({name: "vercel",value: "333",path: "/",});console.log("3、vercel:", response.cookies.get("vercel"));return response;
};
三、在中间件中使用 Headaers
我们可以使用 NextResponse
API
设置请求和响应标头(自 Next.js v13.0.0
起可以设置请求标头)。
见:middleware.ts
/** 三、在中间件中使用 Headers */
export const middleware = (request: NextRequest) => {const headers = new Headers(request.headers);headers.set("token", "this is my token");// 通过 NextResponse.next() 的配置对象来修改请求const response = NextResponse.next({request: {headers: headers, // 修改请求头},});// 通过 response 的 headers 来修改响应头response.headers.set("token", "this is my token");return response;
};
四、在中间件中使用 CORS
我们可以在中间件中设置 CORS
标头以允许跨源请求,包括简单的并已预检要求。
见:middleware.ts
/** 四、在中间件中使用 CORS */
// 定义允许跨域访问的源站列表
const allowedOrigins = ["https://example.com", "https://sub.example.com"];// 定义 CORS 相关的配置选项
const corsOptions = {// 允许的 HTTP 请求方法"Access-Control-Allow-Methods": "GET, POST, PUT, DELETE, OPTIONS",// 允许的请求头"Access-Control-Allow-Headers": "Content-Type, Authorization",
};export const middleware = (request: NextRequest) => {// 获取请求的源站地址,如果没有则设为空字符串const origin = request.headers.get("origin") ?? "";// 检查请求的源站是否在允许列表中const isAllowedOrigin = allowedOrigins.includes(origin);// 判断是否为预检请求(OPTIONS 请求)const isOptions = request.method === "OPTIONS";// 处理预检请求if (isOptions) {// 构建预检响应的头部信息const preflightHeaders = {// 如果是允许的源站,则添加 Access-Control-Allow-Origin 头...(isAllowedOrigin && { "Access-Control-Allow-Origin": origin }),// 展开其他 CORS 配置选项...corsOptions,};// 返回预检响应,状态码默认为 200return NextResponse.json({}, { headers: preflightHeaders });}// 处理非预检请求const response = NextResponse.next();// 为所有响应添加 CORS 头部信息Object.entries(corsOptions).forEach(([key, value]) => {response.headers.set(key, value);});return response;
};// 配置中间件只对 API 路由生效
export const config = {matcher: "/api/:path*",
};
五、如何直接响应
我们可以通过返回 Response
或 NextResponse
实例直接从中间件进行响应。(此功能自 Next.js v13.1.0
开始可用 )
export const config = {matcher: "/api/:function*",
};export const middleware = (request: NextRequest) => {// 鉴权判断if (!isAuthenticated(request)) {// 返回错误信息return new NextResponse(JSON.stringify({ success: false, message: "authentication failed" }),{ status: 401, headers: { "content-type": "application/json" } });}
};