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.pswp.cn/web/67025.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/67025.shtml
英文地址,請注明出處:http://en.pswp.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)

首先介紹一下什么是二叉搜索樹。 二叉搜索樹是一個有序樹: 若它的左子樹不空,則左子樹上所有結點的值均小于它的根結點的值;若它的右子樹不空,則右子樹上所有結點的值均大于它的根結點的值;它的左、右子樹也分別為二叉…