中間件函數(shù)在應(yīng)用的request--reponse周期中漫拭,能夠使用request對(duì)象(req)掀抹、response對(duì)象(res)和next函數(shù)(next)吟秩。能夠?qū)崿F(xiàn)如下功能
- 執(zhí)行邏輯代碼;
- 更改request對(duì)象和response對(duì)象硝烂;
- 結(jié)束request--reponse周期初坠;
- 調(diào)用棧中的下一個(gè)中間件和簸。
tips: 如果當(dāng)前的中間件函數(shù)沒有結(jié)束request--reponse周期,則必須調(diào)用next()碟刺,將控制權(quán)交給下一個(gè)中間件函數(shù)比搭,否則請(qǐng)求將被掛起。 執(zhí)行邏輯代碼的中間件的順序需要在路由handler之前南誊,否則不會(huì)執(zhí)行其代碼身诺,因?yàn)槁酚蒱andler會(huì)結(jié)束掉這個(gè)request-response cycle
Express的應(yīng)用可以使用以下類型的中間件: - 應(yīng)用級(jí)別中間件
- 路由級(jí)別中間件
- 錯(cuò)誤處理中間件
- 內(nèi)置中間件
- 第三方中間件
可以使用可選的掛載路徑(不配置掛載路徑的話默認(rèn)掛載在根目錄下/) 加載應(yīng)用級(jí)別和路由級(jí)別的中間件 。也可以加載一系列的中間件函數(shù)抄囚,這樣會(huì)在掛載點(diǎn)創(chuàng)建一個(gè)中間件系統(tǒng)的子堆棧霉赡。
1. 應(yīng)用級(jí)別中間件
將應(yīng)用級(jí)別的中間件綁定到Express實(shí)例--app上,使用app.use()
和app.METHOD(此METHOD指get幔托、post等方法)
tips: 從一個(gè)路由到另一個(gè)路由(路由使用app.METHOD或router.METHOD定義的)穴亏,使用next('route')
app.get('/user/:id', function (req, res, next) {
// if the user ID is 0, skip to the next route
if (req.params.id === '0') next('route')
// otherwise pass the control to the next middleware function in this stack
else next()
}, function (req, res, next) {
// send a regular response
res.send('regular')
})
// handler for the /user/:id path, which sends a special response
app.get('/user/:id', function (req, res, next) {
res.send('special')
})
2. 路由級(jí)別中間件
同應(yīng)用級(jí)別的中間件用法相同,不同之處的是它是綁定在router實(shí)例(express.Router())上的
tips: 同樣也可以使用next('route') 從一個(gè)路由到另一個(gè)路由(另一個(gè)路由使用router.METHOD定義的)
3. 錯(cuò)誤處理中間件
與其他中間件函數(shù)的定義基本相同重挑,不同之處在于錯(cuò)誤處理函數(shù)多了一個(gè)變量:err嗓化,即它有4個(gè)變量:err, req, res, next
app.use(function(err, req, res, next) {
console.error(err.stack);
res.status(500).send('Something broke!');
});
tips: next() 傳入的參數(shù)除了字符串'route'外,其他參數(shù)會(huì)認(rèn)為出錯(cuò)谬哀,交由錯(cuò)誤處理函數(shù)處理刺覆。若未顯式定義錯(cuò)誤處理函數(shù),則函數(shù)集的末尾有express隱式包含的默認(rèn)錯(cuò)誤處理程序史煎。
4. 內(nèi)置中間件
express.static()谦屑、express.json()、express.urlencoded()等
5. 第三方中間件
如操作cookie的cookie-parser篇梭,
讀取解析的cookie用req.cookies(讀取被簽名的cookie用req.signedCookies)氢橙,讀取cookie字符串用express的req.headers.cookie;
設(shè)置cookie用express的res.cookie(key, value)或res.header('Set-Cookie', 'key=value');
var express = require('express');
var app = express();
var cookieParser = require('cookie-parser');
app.use('cookieParser ');
app.get('/', function(req, res, next){
console.log(req.cookies); // 解析過的object的形式--{ k1: 'v1', k2: 'v2' }。引入了cookie-parser方可使用
console.log(req.headers.cookie);// string的形式--k1=v1; k2=v2恬偷。express原生可以用
res.cookie('key3', 'val3'); // 設(shè)置cookie,express原生可以用
res.send('cookie example');
})
tips:使用session可以用express-session中間件悍手,默認(rèn)是存儲(chǔ)在內(nèi)存中,server重啟后會(huì)丟失袍患,不適用于生產(chǎn)環(huán)境坦康。可以通過設(shè)置store參數(shù) 將session內(nèi)容存儲(chǔ)在數(shù)據(jù)庫(kù)中协怒。
tips:關(guān)于安全問題的兩點(diǎn):
- app.disable('x-powered-by'); reponse中不會(huì)返回X-Powered-By字段(如果不做設(shè)置會(huì)返回server的類型涝焙,如X-Powered-By: Express,可能導(dǎo)致針對(duì)性的攻擊)孕暇;
- 使用session時(shí)仑撞,將cookie中sessionid的key設(shè)置為通用的字符串如sessionID(不設(shè)置的話sessionid默認(rèn)的key為connect.sid),同上一條的原因一樣妖滔,防止黑客針對(duì)你的后臺(tái)類型進(jìn)行針對(duì)性攻擊隧哮。
app.use(session({
name : 'sessionId',
resave:false,
saveUninitialized: false
}));