什么是 express 中間件?中間件在字面上的意思是你在軟件的一層和另一層中間放置的任何東西。express 中間件是在對 express 服務(wù)器請求的生命周期內(nèi)所執(zhí)行的函數(shù)。每個中間件都可以訪問其被附加到的所有路由的 http 請求和響應(yīng)。另外,中間件可以終止 http 請求,也可以用 next 將其傳遞給另一個中間件函數(shù)。中間件的這種“鏈”使你可以對代碼進行劃分并創(chuàng)建可重用的中間件。編寫 express 中間件的要求
你需要安裝一些東西來創(chuàng)建、使用和測試 express 中間件。首先需要 node 和 npm。為確保已經(jīng)安裝,可以運行:
npm -v && node -v你應(yīng)該看到已安裝的 node 和 npm 版本。如果出現(xiàn)錯誤,則需要安裝 node。所有例子都應(yīng)在 node ver 8 和npm ver 5 下使用。
本文使用了 express 4.x 版。這很重要,因為從 3.x 版到 4.x 版有重大的更改。
express中間件:基礎(chǔ)
首先我們使用 express 最基本的內(nèi)置中間件。創(chuà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);中間件解決什么問題?為什么要用它?
假設(shè)你在 web 網(wǎng)絡(luò)服務(wù)器上正在使用 node.js 和 express 運行web應(yīng)用程序。在此應(yīng)用中,你需要登錄的某些頁面。
當(dāng) web 服務(wù)器收到數(shù)據(jù)請求時,express 將為你提供一個請求對象,其中包含有關(guān)用戶及其所請求數(shù)據(jù)的信息。 express 還使你可以訪問響應(yīng)對象,可以在web服務(wù)器響應(yīng)用戶之前對其進行修改。這些對象通常縮短為 req,res。
中間件函數(shù)是使用相關(guān)信息修改 req 和 res 對象的理想場所。例如用戶登錄后,你可以從數(shù)據(jù)庫中獲取其用戶詳細信息,然后將這些詳細信息存儲在 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)錯誤,并且你不想執(zhí)行其他代碼,則不要調(diào)用該函數(shù)。請記住在這種情況下要發(fā)送響應(yīng),否則客戶端將會等待響應(yīng)直到超時。
var app = express();//your normal route handlersapp.get('/user/:id', usermiddleware, usercontroller);中間件鏈
你可以在中間件數(shù)組中或著通過使用多個 app.use 調(diào)用來鏈接中間件:
app.use(middlewarea);app.use(middlewareb);app.get('/', [middlewarec, middlewared], handler);express 收到請求后,與請求相匹配的每個中間件都將會按照初始化的順序運行,直到有終止操作為止。
因此,如果發(fā)生錯誤,則將按順序調(diào)用所有用于處理錯誤的中間件,直到其中一個不再調(diào)用 next() 函數(shù)調(diào)用為止。
express中間件的類型路由器級中間件,例如:router.use內(nèi)置中間件,例如:express.static,express.json,express.urlencoded錯誤處理中間件,例如:app.use(err,req,res,next)第三方中間件,例如:bodyparser、cookieparser路由器級中間件
express.router 使用 express.router 類創(chuàng)建模塊化的、可安裝的路由處理。路由實例是一個完整的中間件和路由系統(tǒng)。
你可以用中間件進行日志記錄、身份驗證等操作。如下所示,以記錄用戶的最新活動并解析身份驗證標頭,用它確定當(dāng)前登錄的用戶并將其添加到 request 對象。該函數(shù)在程序每次收到請求時執(zhí)行。如果有錯誤,它會僅結(jié)束響應(yīng),而不會調(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)置中間件<