Next.js 实战 (十):中间件的魅力,打造更快更安全的应用

什么是中间件?

在 Next.js 中,中间件(Middleware)是一种用于处理每个传入请求的功能。它允许你在请求到达页面之前对其进行修改或响应。

通过中间件,你可以实现诸如日志记录身份验证重定向CORS配置压缩等任务。中间件是构建高效和安全的 web 应用的重要组成部分。

应用场景

身份验证

你可以在中间件中检查用户的身份验证状态,比如从cookie或头部信息中读取JWT令牌,并根据验证结果决定是否允许访问特定页面或API端点。如果验证失败,可以返回401未授权状态码或者重定向到登录页面。
示例代码:

// middleware.js
import { NextResponse } from 'next/server';export function middleware(request) {const token = request.cookies.get('authToken')?.value;if (!token) {// 如果没有令牌,则重定向到登录页面return NextResponse.redirect(new URL('/login', request.url));}// 继续处理链return NextResponse.next();
}

日志记录

中间件非常适合用来记录所有进入应用程序的请求。这可以帮助监控流量模式、诊断问题以及了解用户行为。
示例代码:

// middleware.js
import { NextResponse } from 'next/server';export function middleware(request) {console.log(`Request to ${request.url} at ${new Date().toISOString()}`);// 继续处理链return NextResponse.next();
}

请求/响应转换

可以在请求到达最终目的地之前对请求数据进行预处理,也可以在发送给客户端之前修改响应内容。例如,格式化数据、添加额外的HTTP头、压缩响应体等。
示例代码:

// middleware.js
import { NextResponse } from 'next/server';export async function middleware(request) {// 修改请求体(假设是JSON格式)let modifiedBody = await request.json();modifiedBody.message = "Modified message";// 创建新的请求实例const newReq = new Request(request, {body: JSON.stringify(modifiedBody),});// 获取响应并修改它const response = await fetch(request.nextUrl.pathname, {method: request.method,headers: request.headers,body: newReq.body,});const resClone = await response.clone();const data = await resClone.json();data.newField = "This is a new field"; // 添加新字段// 返回修改后的响应return new Response(JSON.stringify(data), {status: response.status,headers: response.headers,});
}

重定向

基于某些条件(如URL路径、查询参数、用户代理等),你可以使用中间件来执行重定向操作,将用户引导至不同的页面。
示例代码:

// middleware.js
import { NextResponse } from 'next/server';export function middleware(request) {// 如果访问的是旧路径,则重定向到新路径if (request.nextUrl.pathname.startsWith('/login')) {return NextResponse.redirect(new URL('/dashboard', request.url));}// 继续处理链return NextResponse.next();
}

CORS(跨源资源共享)

设置适当的CORS头以允许或限制来自其他域的请求,这对于拥有多个子域名或需要与第三方服务交互的应用非常重要。
示例代码:

// middleware.js
import { NextResponse } from 'next/server';export function middleware(request) {const response = NextResponse.next();// 设置CORS头response.headers.set('Access-Control-Allow-Origin', '*');response.headers.set('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');response.headers.set('Access-Control-Allow-Headers', 'Content-Type, Authorization');return response;
}

限流

防止滥用API接口,可以通过中间件实现速率限制,限制同一IP地址在一定时间内的请求次数。
示例代码:

// middleware.js
import { NextResponse } from 'next/server';
import rateLimit from 'express-rate-limit'; // 需要安装依赖const limiter = rateLimit({windowMs: 1 * 60 * 1000, // 1分钟max: 100, // 每分钟最多100次请求
});export function middleware(request) {return new Promise((resolve, reject) => {limiter(request, {}, (err) => {if (err) {return reject(new NextResponse('Too many requests', { status: 429 }));}resolve(NextResponse.next());});});
}

国际化路由

根据用户的语言偏好或地理位置自动调整网站的语言版本。
示例代码:

// middleware.js
import { NextResponse } from 'next/server';export function middleware(request) {const locale = request.cookies.get('NEXT_LOCALE')?.value || 'en';// 如果不是根路径并且没有包含语言前缀,则添加语言前缀if (!request.nextUrl.pathname.startsWith(`/${locale}`)) {const url = new URL(request.url);url.pathname = `/${locale}${url.pathname}`;return NextResponse.redirect(url);}// 继续处理链return NextResponse.next();
}

静态文件服务

尽管Next.js已经提供了基本的静态文件服务功能,但你可以用中间件来增强这一功能,比如为特定类型的文件提供自定义处理逻辑。
示例代码:

// middleware.js
import { NextResponse } from 'next/server';
import fs from 'fs/promises';export async function middleware(request) {const path = request.nextUrl.pathname;if (path.startsWith('/static-files/')) {try {const filePath = `./public${path}`;const file = await fs.readFile(filePath);return new Response(file, {headers: { 'Content-Type': 'application/octet-stream' },});} catch (error) {return NextResponse.next();}}// 继续处理链return NextResponse.next();
}

config 配置对象

matcher

matcher 是一个非常强大的配置项,它允许你指定中间件应该应用于哪些路径。你可以通过正则表达式或通配符模式来匹配URL路径。

  • 通配符:可以使用 * 来表示任意字符序列。
  • 正则表达式:支持完整的正则表达式语法,但需要使用反斜杠进行转义。
export const config = {matcher: ['/about', '/dashboard/:path*', '/users/:uid'],
};

unstable_ignorePaths

这个配置项可以让中间件忽略某些路径,即不对其应用中间件逻辑。这对于排除不需要处理的资源或者避免循环重定向等问题非常有用。

export const config = {unstable_ignorePaths: ['/api/*', '/static/*'],
};

这里,所有以 /api /开头和静态资源路径都将被忽略,不会受到中间件的影响。

maxDuration

maxDuration 定义了中间件函数的最大执行时间(以秒为单位)。如果中间件执行时间超过了这个值,Next.js将会抛出错误。这有助于防止长时间运行的任务阻塞请求处理。

export const config = {maxDuration: 5, // 中间件最大执行时间为5秒
};

regions

regions 配置项指定了中间件应该部署到的地理区域。这对于希望减少延迟、提高性能的应用来说非常重要,因为它可以让中间件尽可能靠近用户部署。

export const config = {regions: ['us-east-1', 'eu-west-1'], // 在美国东部和欧洲西部部署
};

下面是一个结合了多个config配置项的例子:

// middleware.js
import { NextResponse } from 'next/server';export function middleware(request) {// 中间件逻辑...return NextResponse.next();
}export const config = {matcher: ['/about', '/dashboard/:path*', '/users/:uid'],unstable_ignorePaths: ['/api/*', '/static/*'],maxDuration: 10,regions: ['us-east-1', 'eu-west-1'],
};

总结

总之,Next.js中间件不仅仅是一个简单的请求处理器,它更像是一个构建模块,允许开发者以一种非侵入式的方式对HTTP请求进行预处理和后处理。这不仅简化了代码逻辑,提高了代码的可维护性,而且还有助于创建更加快速、安全和用户友好的Web体验。无论你是刚开始接触Next.js的新手,还是已经熟悉框架的老手,掌握中间件的使用都将为你的项目带来显著的价值。

Github:next-admin

线上预览地址:Next Admin

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/67025.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ElasticSearch-文档元数据乐观并发控制

文章目录 什么是文档?文档元数据文档的部分更新Update 乐观并发控制 最近日常工作开发过程中使用到了 ES,最近在检索资料的时候翻阅到了 ES 的官方文档,里面对 ES 的基础与案例进行了通俗易懂的解释,读下来也有不少收获&#xff0…

实验二 数据库的附加/分离、导入/导出与备份/还原

实验二 数据库的附加/分离、导入/导出与备份/还原 一、实验目的 1、理解备份的基本概念,掌握各种备份数据库的方法。 2、掌握如何从备份中还原数据库。 3、掌握数据库中各种数据的导入/导出。 4、掌握数据库的附加与分离,理解数据库的附加与分离的作用。…

技术中台与终搜——2

文章目录 5、语言处理与自动补全技术探测5.1 自定义语料库5.1.1 语料库映射OpenAPI5.1.2 语料库文档OpenAPI 5.2 产品搜索与自动补全5.2.1 汉字补全OpenAPI5.2.2 拼音补全OpenAPI 5.3 产品搜索与语言处理5.3.1 什么是语言处理(拼写纠错)5.3.2 语言处理Op…

15_业务系统基类

创建脚本 SystemRoot.cs 因为 业务系统基类的子类 会涉及资源加载服务层ResSvc.cs 和 音乐播放服务层AudioSvc.cs 所以在业务系统基类 提取引用资源加载服务层ResSvc.cs 和 音乐播放服务层AudioSvc.cs 并调用单例初始化 using UnityEngine; // 功能 : 业务系统基类 public c…

k8s优雅重启

理论上处于terminating状态的pod,k8s 就会把它从service中移除了,只用配置一个优雅停机时长就行了。kubectl get endpoints 验证 因此,优雅重新的核心问题,是怎么让空闲长连接关闭,再等待处理中的请求执行完。 一些底…

【Linux】华为服务器使用U盘安装统信操作系统

目录 一、准备工作 1.1 下载UOS官方系统 1.2制作启动U盘 1.3 服务器智能管理系统iBMC 二、iBMC设置U盘启动 一、准备工作 1.1 下载UOS官方系统 服务器CPU的架构是x86-64还是aarch64),地址:统信UOS生态社区 - 打造操作系统创…

27. 【.NET 8 实战--孢子记账--从单体到微服务】--简易报表--报表服务

报表是每个记账应用所具备的功能,要实现报表功能就需要把账本的核心功能(记账)完成,因此报表服务作为本专栏第一部分单体应用开发中最后一个要实现的功能,这一篇文章很简单,我们一起来实现一个简单的报表服…

基于 Node.js 的天气查询系统实现(附源码)

项目概述 这是一个基于 Node.js 的全栈应用,前端使用原生 JavaScript 和 CSS,后端使用 Express 框架,通过调用第三方天气 API 实现天气数据的获取和展示。 主要功能 默认显示多个主要城市的天气信息 支持城市天气搜索 响应式布局设计 深色主题界面 优雅的加载动画 技术栈 …

cursor重构谷粒商城04——vagrant技术快速部署虚拟机

前言:这个系列将使用最前沿的cursor作为辅助编程工具,来快速开发一些基础的编程项目。目的是为了在真实项目中,帮助初级程序员快速进阶,以最快的速度,效率,快速进阶到中高阶程序员。 本项目将基于谷粒商城…

leetcode 面试经典 150 题:简化路径

链接简化路径题序号71题型字符串解法栈难度中等熟练度✅✅✅ 题目 给你一个字符串 path ,表示指向某一文件或目录的 Unix 风格 绝对路径 (以 ‘/’ 开头),请你将其转化为 更加简洁的规范路径。 在 Unix 风格的文件系统中规则如下…

如何在gitee/github上面搭建obsidian的图床

在搭建图床之前我们需要知道图床是一个什么东西,图床顾名思义就是存放图片的地方,那么我们为什么要搭建图床呢?因为我们在写博客的时候,很多同学都是在本地使用typora或者是obsidian进行markdown语法的文章的书写,文件格式通常都是…

JVM堆空间

JVM(Java虚拟机)堆空间是Java内存管理的核心区域之一,用于存储Java对象实例。以下是关于JVM堆空间的详细介绍: 1. 堆空间的作用 • 存储对象实例:几乎所有的Java对象实例(通过new关键字创建的对象&#xf…

Redis 的热 Key(Hot Key)问题及解决方法

Redis 的热 Key(Hot Key)问题及解决方法 1. 什么是 Redis 热 Key? Redis 热 Key(Hot Key)指的是访问频率极高的 Key,通常会造成以下问题: 单 Key 访问量过大:热点 Key 可能被高并…

SSM东理咨询交流论坛

🍅点赞收藏关注 → 添加文档最下方联系方式咨询本源代码、数据库🍅 本人在Java毕业设计领域有多年的经验,陆续会更新更多优质的Java实战项目希望你能有所收获,少走一些弯路。🍅关注我不迷路🍅 项目视频 js…

http的请求体各项解析

一、前言 做Java开发的人员都知道,其实我们很多时候不单单在写Java程序。做的各种各样的系统,不管是PC的 还是移动端的,还是为别的系统提供接口。其实都离不开http协议或者https 这些东西。Java作为编程语言,再做业务开发时&#…

gradle生命周期钩子函数

文章目录 0. 总结表格1. 构建初始阶段gradle.settingsEvaluated()gradle.projectsLoaded() 2. 配置阶段gradle.beforeProject()gradle.afterProject()gradle.projectEvaluated()gradle.afterEvaluate()gradle.taskGraph.whenReady 3. 执行阶段gradle.taskGraph.beforeTaskgradl…

Qt Enter和HoverEnter事件

介绍 做PC开发的过程中或多或少都会接触到鼠标的悬停事件,Qt中处理鼠标悬停有Enter和HoverEnter两种事件 相同点 QEvent::Enter对应QEnterEvent,描述的是鼠标进入控件坐标范围之内的行为,QEnterEvent可以抓取鼠标的位置;QEvent…

【云安全】云原生-Docker(五)容器逃逸之漏洞利用

漏洞利用逃逸 通过漏洞利用实现逃逸,主要分为以下两种方式: 1、操作系统层面的内核漏洞 这是利用宿主机操作系统内核中的安全漏洞,直接突破容器的隔离机制,获得宿主机的权限。 攻击原理:容器本质上是通过 Linux 的…

如何优化深度学习模型来提高错别字检测准确率?

为了优化深度学习模型以提高错别字检测的准确率,可以从以下几个方面入手: 1. 数据增强 数据增强是提高模型泛化能力的有效方法。通过在训练数据中引入噪声,模型可以学习到更多变的模式,从而提高对未见数据的识别能力。 删除字符:以一定概率删除文本中的一个字符。增加字…

二叉搜索树中的搜索(力扣700)

首先介绍一下什么是二叉搜索树。 二叉搜索树是一个有序树: 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值;若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值;它的左、右子树也分别为二叉…