官术网_书友最值得收藏!

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。

主站蜘蛛池模板: 马山县| 黔南| 南京市| 天水市| 天峻县| 红桥区| 南郑县| 南江县| 湖南省| 孝昌县| 营口市| 贵南县| 濮阳市| 松原市| 米泉市| 新乡县| 伊宁市| 历史| 两当县| 广昌县| 淅川县| 梅州市| 和硕县| 浮山县| 肥东县| 武宣县| 天祝| 德安县| 岑溪市| 南华县| 克拉玛依市| 泗阳县| 桃江县| 黑山县| 乐平市| 兖州市| 蒲江县| 广元市| 奉新县| 陈巴尔虎旗| 临城县|