書名: Node.js+Webpack開發(fā)實(shí)戰(zhàn)作者名: 夏磊本章字?jǐn)?shù): 1004字更新時(shí)間: 2021-03-26 21:53:51
4.6 中間件
中間件是一個(gè)函數(shù),在應(yīng)用的請(qǐng)求-響應(yīng)周期中,能夠訪問(wèn)請(qǐng)求對(duì)象、響應(yīng)對(duì)象和next函數(shù)。
中間件可以執(zhí)行以下任務(wù):
· 執(zhí)行邏輯代碼。
· 更改請(qǐng)求和響應(yīng)對(duì)象。
· 結(jié)束請(qǐng)求-響應(yīng)周期。
· 調(diào)用下一個(gè)中間件。
如果當(dāng)前的中間件沒(méi)有調(diào)用next(),也沒(méi)有結(jié)束請(qǐng)求-響應(yīng)周期,則該請(qǐng)求將被掛起。
中間件有路由中間件和全局中間件兩種。全局中間件對(duì)任何請(qǐng)求都會(huì)生效,路由中間件只對(duì)特定的路由生效。
4.6.1 全局中間件
以下是全局的日志中間件示例,該中間件打印當(dāng)前的請(qǐng)求方法、請(qǐng)求路徑以及User-Agent。

訪問(wèn)http://localhost:8080,客戶端會(huì)收到Hello World響應(yīng),并且在終端會(huì)輸出以下日志:
GET / "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.87 Safari/537.36"
GET /favicon.ico "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.87 Safari/537.36"
訪問(wèn)http://localhost:8080/user,客戶端會(huì)收到user響應(yīng),終端同樣會(huì)輸出請(qǐng)求日志。
4.6.2 路由中間件
還是以剛才的中間件為例,不過(guò)我們將其掛載到特定的路由上。

訪問(wèn)http://localhost:8080,終端會(huì)輸出請(qǐng)求日志,但是訪問(wèn)http://localhost:8080/user時(shí)終端不會(huì)輸出請(qǐng)求日志。
4.6.3 可配置的中間件
在請(qǐng)求對(duì)象這一節(jié)中,我們使用了如下代碼來(lái)掛載中間件。
app.use(cookieParser());
在上面的內(nèi)容中,我們使用的下面代碼。
app.use(logger);
cookieParser()是函數(shù)調(diào)用,支持傳入配置,并且返回一個(gè)中間件。cookieParser()的代碼結(jié)構(gòu)如下:
function cookieParser(options) { return function(req, resp, next) { }; }
我們針對(duì)日志中間件做一下修改來(lái)支持配置:

4.6.4 Cookie中間件
在前面的內(nèi)容中我們使用cookie-parser來(lái)讀取cookie,本節(jié)將和大家一起來(lái)編寫一個(gè)cookie-parser。
通過(guò)請(qǐng)求報(bào)頭可以獲取原始的cookie請(qǐng)求報(bào)頭:

可以看到每個(gè)cookie之間以分號(hào)分隔,cookie的名字和cookie值通過(guò)等號(hào)分隔,所以編寫cookie的思路如下:
(1)讀取請(qǐng)求報(bào)頭的cookie字段。
(2)使用";"來(lái)分隔每個(gè)cookie。
(3)針對(duì)單個(gè)cookie,使用"="分隔名字和值。
(4)將獲取到的cookie名字和值掛載到req.cookies對(duì)象上。

4.6.5 響應(yīng)時(shí)長(zhǎng)中間件
有些場(chǎng)景下需要統(tǒng)計(jì)請(qǐng)求開始到請(qǐng)求結(jié)束階段,服務(wù)器處理請(qǐng)求所花費(fèi)的時(shí)長(zhǎng),目前的中間件是無(wú)法獲取到“請(qǐng)求結(jié)束”事件的。
Express的響應(yīng)對(duì)象提供了“finish”事件來(lái)告知請(qǐng)求結(jié)束事件。我們基于該事件來(lái)編寫響應(yīng)時(shí)長(zhǎng)中間件。

訪問(wèn)http://localhost:8080時(shí),終端會(huì)打印響應(yīng)時(shí)長(zhǎng)。
監(jiān)聽resp事件需要使用once,使用on會(huì)引起內(nèi)存泄露。
4.6.6 靜態(tài)資源中間件
為了提供圖片、CSS和JS之類的靜態(tài)文件的訪問(wèn),可以使用內(nèi)置的express.static中間件。
express.static(root, [options])
· root:服務(wù)器文件夾路徑。
· options:選項(xiàng)。
以下是一個(gè)提供靜態(tài)資源訪問(wèn)的示例。
項(xiàng)目目錄結(jié)構(gòu)如下:

// 導(dǎo)入express模塊 const express = require('express'); const app = express(); app.use(express.static('./public')); // 將靜態(tài)資源中間件掛載到全局 // 開啟監(jiān)聽 app.listen(8080, () => { console.log('listen on 8080'); });
上面的代碼需要訪問(wèn)http://localhost:8080/css/style.css才能獲取style.css。
也就是說(shuō)public目錄在請(qǐng)求鏈接中不能出現(xiàn),如果需要將靜態(tài)資源掛載到/public這個(gè)路由前綴下,可以使用下面的代碼:
app.use('/public', express.static('./public'));
上面的代碼需要訪問(wèn)http://localhost:8080/public/css/style.css才能獲取style.css。
- 極簡(jiǎn)算法史:從數(shù)學(xué)到機(jī)器的故事
- Azure IoT Development Cookbook
- Mastering Concurrency in Go
- Bootstrap Essentials
- Java 9模塊化開發(fā):核心原則與實(shí)踐
- Creating Stunning Dashboards with QlikView
- OpenResty完全開發(fā)指南:構(gòu)建百萬(wàn)級(jí)別并發(fā)的Web應(yīng)用
- JBoss:Developer's Guide
- Swift語(yǔ)言實(shí)戰(zhàn)晉級(jí)
- Scala Functional Programming Patterns
- OpenCV Android開發(fā)實(shí)戰(zhàn)
- 精通Spring:Java Web開發(fā)與Spring Boot高級(jí)功能
- Visual C++從入門到精通(第2版)
- Visual Basic 程序設(shè)計(jì)實(shí)踐教程
- Android技術(shù)內(nèi)幕(系統(tǒng)卷)