什么是 express 中間件?中間件在字面上的意思是你在軟件的一層和另一層中間放置的任何東西。express 中間件是在對(duì) express 服務(wù)器請(qǐng)求的生命周期內(nèi)所執(zhí)行的函數(shù)。每個(gè)中間件都可以訪問(wèn)其被附加到的所有路由的 http 請(qǐng)求和響應(yīng)。另外,中間件可以終止 http 請(qǐng)求,也可以用 next 將其傳遞給另一個(gè)中間件函數(shù)。中間件的這種“鏈”使你可以對(duì)代碼進(jìn)行劃分并創(chuàng)建可重用的中間件。編寫(xiě) express 中間件的要求
你需要安裝一些東西來(lái)創(chuàng)建、使用和測(cè)試 express 中間件。首先需要 node 和 npm。為確保已經(jīng)安裝,可以運(yùn)行:
npm -v && node -v你應(yīng)該看到已安裝的 node 和 npm 版本。如果出現(xiàn)錯(cuò)誤,則需要安裝 node。所有例子都應(yīng)在 node ver 8 和npm ver 5 下使用。
本文使用了 express 4.x 版。這很重要,因?yàn)閺?3.x 版到 4.x 版有重大的更改。
express中間件:基礎(chǔ)
首先我們使用 express 最基本的內(nèi)置中間件。創(chuàng)建一個(gè)新項(xiàng)目并 npm 初始化它…
npm initnpm install express --savecreate server.js and paste the following code:const express = require('express');const app = express();app.get('/', (req, res, next) => { res.send('welcome home');});app.listen(3000);中間件解決什么問(wèn)題?為什么要用它?
假設(shè)你在 web 網(wǎng)絡(luò)服務(wù)器上正在使用 node.js 和 express 運(yùn)行web應(yīng)用程序。在此應(yīng)用中,你需要登錄的某些頁(yè)面。
當(dāng) web 服務(wù)器收到數(shù)據(jù)請(qǐng)求時(shí),express 將為你提供一個(gè)請(qǐng)求對(duì)象,其中包含有關(guān)用戶及其所請(qǐng)求數(shù)據(jù)的信息。 express 還使你可以訪問(wèn)響應(yīng)對(duì)象,可以在web服務(wù)器響應(yīng)用戶之前對(duì)其進(jìn)行修改。這些對(duì)象通??s短為 req,res。
中間件函數(shù)是使用相關(guān)信息修改 req 和 res 對(duì)象的理想場(chǎng)所。例如用戶登錄后,你可以從數(shù)據(jù)庫(kù)中獲取其用戶詳細(xì)信息,然后將這些詳細(xì)信息存儲(chǔ)在 res.user 中。
中間件函數(shù)是什么樣的?
async function usermiddleware (req, res, next) { try { const userdata = await getuserdata(req.params.id); //see app.get below if(userdata) { req.user = userdata; next(); } } catch(error) { res.status(500).send(error.message); //replace with proper error handling }}如果出現(xiàn)錯(cuò)誤,并且你不想執(zhí)行其他代碼,則不要調(diào)用該函數(shù)。請(qǐng)記住在這種情況下要發(fā)送響應(yīng),否則客戶端將會(huì)等待響應(yīng)直到超時(shí)。
var app = express();//your normal route handlersapp.get('/user/:id', usermiddleware, usercontroller);中間件鏈
你可以在中間件數(shù)組中或著通過(guò)使用多個(gè) app.use 調(diào)用來(lái)鏈接中間件:
app.use(middlewarea);app.use(middlewareb);app.get('/', [middlewarec, middlewared], handler);express 收到請(qǐng)求后,與請(qǐng)求相匹配的每個(gè)中間件都將會(huì)按照初始化的順序運(yùn)行,直到有終止操作為止。
因此,如果發(fā)生錯(cuò)誤,則將按順序調(diào)用所有用于處理錯(cuò)誤的中間件,直到其中一個(gè)不再調(diào)用 next() 函數(shù)調(diào)用為止。
express中間件的類(lèi)型路由器級(jí)中間件,例如:router.use內(nèi)置中間件,例如:express.static,express.json,express.urlencoded錯(cuò)誤處理中間件,例如:app.use(err,req,res,next)第三方中間件,例如:bodyparser、cookieparser路由器級(jí)中間件
express.router 使用 express.router 類(lèi)創(chuàng)建模塊化的、可安裝的路由處理。路由實(shí)例是一個(gè)完整的中間件和路由系統(tǒng)。
你可以用中間件進(jìn)行日志記錄、身份驗(yàn)證等操作。如下所示,以記錄用戶的最新活動(dòng)并解析身份驗(yàn)證標(biāo)頭,用它確定當(dāng)前登錄的用戶并將其添加到 request 對(duì)象。該函數(shù)在程序每次收到請(qǐng)求時(shí)執(zhí)行。如果有錯(cuò)誤,它會(huì)僅結(jié)束響應(yīng),而不會(huì)調(diào)用后續(xù)的中間件或路由處理。
var router = express.router()//load router-level middleware by using the router.use() and router.method() functions.//the following example creates a router as a module, loads a middleware function in it,// defines some routes, and mounts the router module on a path in the main app.var express = require(‘express’);var router = express.router();// a middleware function with no mount path. this code is executed for// every request to the router// loggingasync function logmiddleware (req, res, next) { try { console.log(req.user.id, new date()); next(); } catch() { res.status(500).send(error.message); }}// authentication async function checkauthentication(req, res, next) => {// check header or url parameters or post parameters for tokenconst token = req.body.token || req.query.token || req.headers['x-access-token'] || req.headers['authorization']; if (token) { try { // verifies secret req.decoded = await jwt.verify(token, config.secret) let checkuser = await authenticatetokenhelper.getuserdetail(req); // if everything is good, save to request for use in other routes if (checkuser) { req.user = req.decoded next() } else { return res.status(403).json({ message: responsemessage.noauthorized }) } } catch (err) { return res.status(401).json({ message: responsemessage.invalidtoken }) } } else { // if there is no token return res.status(400).json({ message: responsemessage.invalidrequest }) }}router.use(logmiddleware); router.get('/user, checkauthentication, handler);內(nèi)置中間件<