总览
中间件功能是可以访问请求对象(req
),响应对象(res
)以及next
应用程序的请求-响应周期中的功能的功能。该next
功能是Express路由器中的功能,当调用该功能时,它会在当前中间件之后执行中间件。
中间件功能可以执行以下任务:
- 执行任何代码。
- 更改请求和响应对象。
- 结束请求-响应周期。
- 调用堆栈中的下一个中间件。
如果当前中间件功能没有结束请求-响应周期,则必须调用next()
将控制权传递给下一个中间件功能。否则,该请求将被挂起。
下图显示了中间件函数调用的元素:
中间件功能适用的HTTP方法。 中间件功能适用的路径(路由)。 中间件功能。 中间件函数的回调参数,按照惯例称为“ next”。 中间件函数的HTTP 响应参数,按照惯例称为“ res”。 中间件功能的HTTP 请求参数,按照惯例称为“ req”。 |
|
---|---|
从Express 5开始,返回Promise的中间件函数将next(value)
在拒绝或引发错误时调用。next
将使用拒绝值或引发的错误来调用。
示例
这是一个简单的“ Hello World” Express应用程序的示例。本文的其余部分将定义并向应用程序添加三个中间件功能:一个名为myLogger
打印简单的日志消息,一个称为requestTime
显示HTTP请求的时间戳,另一个称为validateCookies
验证传入的cookie。
var express = require('express')
var app = express()
app.get('/', function (req, res) {
res.send('Hello World!')
})
app.listen(3000)
中间件myLogger
这是一个称为“ myLogger”的中间件功能的简单示例。当对应用程序的请求通过时,此功能仅显示“已记录”。中间件函数被分配给名为的变量myLogger
。
var myLogger = function (req, res, next) {
console.log('LOGGED')
next()
}
请注意上面的呼叫next()
。调用此函数将调用应用程序中的下一个中间件函数。该next()
函数不是Node.js或Express API的一部分,而是传递给中间件函数的第三个参数。该next()
函数可以命名为任何东西,但按照惯例,它总是命名为“ next”。为避免混淆,请始终使用此约定。
要加载中间件功能,请调用app.use()
,指定中间件功能。例如,以下代码myLogger
在路由到根路径(/)之前加载中间件功能。
var express = require('express')
var app = express()
var myLogger = function (req, res, next) {
console.log('LOGGED')
next()
}
app.use(myLogger)
app.get('/', function (req, res) {
res.send('Hello World!')
})
app.listen(3000)
每次应用收到请求时,它将消息“ LOGGED”记录到终端。
中间件加载的顺序很重要:首先加载的中间件功能也将首先执行。
如果myLogger
在到达根路径的路由之后加载,则请求永远不会到达请求,并且应用程序不会显示“ LOGGED”,因为根路径的路由处理程序会终止请求-响应周期。
中间件函数myLogger
只是打印一条消息,然后通过调用该next()
函数将请求传递给堆栈中的下一个中间件函数。
中间件requestTime
接下来,我们将创建一个名为“ requestTime”的中间件函数,并将一个名为的属性添加requestTime
到请求对象。
var requestTime = function (req, res, next) {
req.requestTime = Date.now()
next()
}
该应用程序现在使用requestTime
中间件功能。此外,根路径路由的回调函数使用中间件函数添加到的属性req
(请求对象)。
var express = require('express')
var app = express()
var requestTime = function (req, res, next) {
req.requestTime = Date.now()
next()
}
app.use(requestTime)
app.get('/', function (req, res) {
var responseText = 'Hello World!<br>'
responseText += '<small>Requested at: ' + req.requestTime + '</small>'
res.send(responseText)
})
app.listen(3000)
现在,当您向应用程序的根目录发出请求时,该应用程序将在浏览器中显示您请求的时间戳。
中间件validateCookies
最后,我们将创建一个中间件功能,该功能验证传入的Cookie并在Cookie无效的情况下发送400响应。
这是一个使用外部异步服务验证Cookie的示例函数。
async function cookieValidator (cookies) {
try {
await externallyValidateCookie(cookies.testCookie)
} catch {
throw new Error('Invalid cookies')
}
}
在这里,我们使用cookie-parser
中间件从req
对象解析传入的cookie ,并将它们传递给我们的cookieValidator
函数。该validateCookies
中间件返回一个承诺,在拒绝将自动触发我们的错误处理程序。
var express = require('express')
var cookieParser = require('cookie-parser')
var cookieValidator = require('./cookieValidator')
var app = express()
async function validateCookies (req, res, next) {
await cookieValidator(req.cookies)
next()
}
app.use(cookieParser())
app.use(validateCookies)
// error handler
app.use(function (err, req, res, next) {
res.status(400).send(err.message)
})
app.listen(3000)
注意next()
after是如何调用的await cookieValidator(req.cookies)
。这确保了如果cookieValidator
解决,堆栈中的下一个中间件将被调用。如果您向next()
函数传递任何内容(字符串'route'
或除外'router'
),Express都会将当前请求视为错误,并会跳过所有剩余的无错误处理路由和中间件函数。
因为您可以访问请求对象,响应对象,堆栈中的下一个中间件函数以及整个Node.js API,所以中间件函数的可能性是无限的。
有关Express中间件的更多信息,请参见:使用Express中间件。
可配置的中间件
如果您需要可配置的中间件,请导出一个接受选项对象或其他参数的函数,然后再根据输入参数返回中间件实现。
文件: my-middleware.js
module.exports = function (options) {
return function (req, res, next) {
// 根据options配置实施中间件方法
next()
}
}
现在可以如下所示使用中间件。
var mw = require('./my-middleware.js')
app.use(mw({ option1: '1', option2: '2' }))